### Install Dependencies and Start DApp (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Installs project dependencies using npm and then starts the development server for the dApp. This command is run from the 'frontend' directory. ```bash npm i && npm run dev ``` -------------------------------- ### Starting Local CKB Devnet with offckb (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/README.md Execute this command using the installed offckb tool to start a local CKB development network, which provides a blockchain environment for testing dApp examples. ```Shell offckb node ``` -------------------------------- ### Clone and Start Dapp Example (Generic) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/store-data-on-cell/README.md Clones the repository containing the example, navigates to the specific example directory, installs project dependencies using yarn, and starts the application. ```sh git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/store-data-on-cell yarn && yarn start ``` -------------------------------- ### Run CKB Example Application (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/_SetupProjectContent.mdx This command installs project dependencies using `yarn`, sets the `NETWORK` environment variable to `devnet`, and then starts the application using `yarn start`. This is typically used to run the example against a local development network. ```bash yarn && NETWORK=devnet yarn start ``` -------------------------------- ### Setup CKB Duktape Template (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Commands to clone the CKB Duktape template repository, navigate into the project directory, install necessary npm dependencies, and build the initial project to ensure the setup is working correctly. ```Shell export TOP=$(pwd) git clone https://github.com/xxuejie/ckb-duktape-template htlc-template cd htlc-template npm install npm run build ``` -------------------------------- ### Example Application Start Output (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/_SetupProjectContent.mdx This snippet shows the expected output when the example application is successfully started. It indicates that the `parcel` bundler is running, the server is available at `http://localhost:1234`, and the build process completed quickly. ```bash $ parcel index.html\nServer running at http://localhost:1234\n✨ Built in 66ms ``` -------------------------------- ### Setup and Run Omnilock-Solana Example (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/omnilock.mdx Commands to build the Lumos project, navigate to the Omnilock-Solana example directory, and start the example application. ```bash npm run build cd examples/omni-lock-solana npm start ``` -------------------------------- ### Installing offckb Globally (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/README.md Use npm to install the offckb command-line tool globally. This tool is required to start a local CKB development network. ```Shell npm install -g offckb ``` -------------------------------- ### Install OffCKB CLI - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the OffCKB command-line interface globally using npm. OffCKB sets up a local CKB Devnet for testing dApps. ```bash npm install -g @offckb/cli ``` -------------------------------- ### Navigate to Frontend Directory (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Changes the current directory to the 'frontend' workspace, which is necessary before installing dependencies and starting the dApp. ```bash cd frontend ``` -------------------------------- ### Install Cargo-generate (≥0.17.0) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Install Cargo-generate, a tool to create new Rust projects from templates, simplifying project setup. Version ≥0.17.0 is recommended. ```bash cargo install cargo-generate ``` -------------------------------- ### Install Git (≥2.40.0) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Install Git, a version control system for tracking code changes. Version ≥2.40.0 is recommended. ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install git ``` ```bash sudo apt install git ``` -------------------------------- ### Clone Repository and Start Dapp Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-transfer/README.md Clones the example repository from GitHub, navigates into the simple-transfer directory, installs project dependencies using yarn, and starts the Dapp. ```Shell git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/simple-transfer yarn && yarn start ``` -------------------------------- ### Installing OffCKB CLI (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Installs the offCKB command-line interface globally using npm. This tool is essential for quickly setting up a local CKB development environment and using pre-built boilerplates. ```bash npm install -g @offckb/cli ``` -------------------------------- ### Clone Repository and Start App Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/create-dob/README.md Clones the example repository from GitHub, navigates into the Dapp directory, installs project dependencies using yarn, and then starts the application. ```Shell git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/create-dob yarn && yarn start ``` -------------------------------- ### Start CKB Devnet with offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/xudt/README.md Uses the globally installed `offckb` tool to start a local CKB development network node. ```Shell offckb node ``` -------------------------------- ### OffCKB Project Creation Success Output (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Displays the console output indicating successful cloning and setup of the project template after selecting a framework during the `offckb create` process. ```bash Cloning into '/Users/Desktop/offckb/templates/temp-clone-folder'... Folder examples/next-js-template downloaded successfully from https://github.com/nervosnetwork/docs.nervos.org and moved to /Users/nervosDocs/Desktop/offckb/my-dapp-project ``` -------------------------------- ### Start Frontend Development Server Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Navigate into the frontend directory of your project, install dependencies, and start the local development server to run the frontend application. ```bash cd frontend && npm i & npm run dev ``` -------------------------------- ### Install offckb CLI Tool Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/store-data-on-cell/README.md Installs the 'offckb' command-line interface tool globally using npm. This tool is required to start and manage a local CKB development network (devnet). ```sh npm install -g offckb ``` -------------------------------- ### Setting up CKB Duktape Template - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Provides the necessary shell commands to clone the CKB Duktape template repository from GitHub, navigate into the created directory, install project dependencies using npm, and build the project to ensure the setup is correct and functional. ```Shell export TOP=$(pwd) git clone https://github.com/xxuejie/ckb-duktape-template htlc-template cd htlc-template npm install # now you can try building the script first to ensure everything works npm run build ``` -------------------------------- ### CRA App Initialization Response Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Displays the output from the `create-react-app` command, indicating the successful creation of the React application directory, the installation of packages (react, react-dom, react-scripts), and the total time taken. ```bash Creating a new React app in /Users/nervosDocs/Desktop/offckb/my-cra-dapp. Installing packages. This might take a couple of minutes. Installing react, react-dom, and react-scripts with cra-template-typescript... added 1489 packages in 2m ``` -------------------------------- ### Run Dapp Example on CKB Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/store-data-on-cell/README.md Sets the NETWORK environment variable to 'devnet', changes the directory to the example folder, installs dependencies (if needed), and starts the application configured to connect to the local CKB devnet. ```sh export NETWORK=devnet cd write-and-read-message yarn && yarn start ``` -------------------------------- ### Setup CKB Script Debugger Environment (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Sets up the project directory and installs necessary Node.js packages for the CKB script debugging environment, including CKB SDK, Molecule, and CRC32. ```shell $ cd $TOP $ mkdir htlc-runner $ cd htlc-runner $ npm init $ npm install --save @nervosnetwork/ckb-sdk-core $ npm install --save @nervosnetwork/ckb-sdk-utils $ npm install --save molecule-javascript $ npm install --save crc32 ``` -------------------------------- ### Start CKB Devnet using offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/store-data-on-cell/README.md Starts a local CKB development network node using the installed 'offckb' CLI tool. This command initiates a local blockchain environment for testing the Dapp. ```sh offckb node ``` -------------------------------- ### OffCKB Devnet Startup Output (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Shows the console output when starting the CKB Devnet with `offckb node`. It includes messages about downloading CKB if necessary, initializing the configuration, and the CKB node's initial output. ```bash /bin/sh: /Users/nervosDocs/.nvm/versions/node/v18.12.1/lib/node_modules/@offckb/cli/target/ckb/ckb: No such file or directory /Users/nervosDocs/.nvm/versions/node/v18.12.1/lib/node_modules/@offckb/cli/target/ckb/ckb not found, download and install the new version 0.113.1.. CKB installed successfully. init Devnet config folder: /Users/nervosDocs/.nvm/versions/node/v18.12.1/lib/node_modules/@offckb/cli/target/devnet modified /Users/nervosDocs/.nvm/versions/node/v18.12.1/lib/node_modules/@offckb/cli/target/devnet/ckb-miner.toml CKB output: 2024-03-20 07:56:44.765 +00:00 main INFO sentry sentry is disabled CKB output: 2024-03-20 07:56:44.766 +00:00 main INFO ckb_bin::helper raise_fd_limit newly-increased limit: 61440 CKB output: 2024-03-20 07:56:44.854 +00:00 main INFO ckb_bin::subcommand::run ckb version: 0.113.1 (95ad24b 2024-01-31) CKB output: 2024-03-20 07:56:45.320 +00:00 main INFO ckb_db_migration Init database version 20230206163640 CKB output: 2024-03-20 07:56:45.329 +00:00 main INFO ckb_launcher Touch chain spec hash: Byte32(0x3036c73473a371f3aa61c588c38924a93fb8513e481fa7c8d884fc4cf5fd368a) ``` -------------------------------- ### Install CKB-Debugger (≥0.113.0) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Install CKB-Debugger, a CLI tool for off-chain CKB Script development and testing. Version ≥0.113.0 is recommended. ```bash cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger ``` -------------------------------- ### Starting the Local CKB Devnet with OffCKB (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Starts a local CKB development network (Devnet) using the offCKB CLI. This command makes the Devnet RPC endpoint available at `localhost:8114` for development and testing. ```bash offckb node ``` -------------------------------- ### Starting CKB Miner (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This simple shell script demonstrates how to navigate to the project directory and start a CKB miner instance using the previously initialized data directory. ```Shell $ cd $TOP $ $CKB miner -C ckb-data ``` -------------------------------- ### Creating a New dApp Project with OffCKB (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Initializes a new full-stack dApp project using the offCKB CLI. Replace with the desired project name. The command will prompt you to select a frontend framework. ```bash offckb create ``` -------------------------------- ### Build and Run Omnilock-Metamask Example (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/omnilock.mdx These commands build the project, create a release build, navigate into the specific Omnilock-Metamask example directory, and then start the example application. ```Shell npm run build npm run build-release cd examples/omni-lock-metamask npm start ``` -------------------------------- ### OffCKB Project Creation Prompt Output (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Shows the interactive prompt output when running `offckb create`, illustrating how to select a bare template using arrow keys from the available options. ```bash ? Select a bare template Remix-Vite Bare Templates > Next.js Bare Templates --- A full-stack template with Next.js framework and ckb-script-templates, [next.js,tailwindcss,ckb-script-templates,typescript,rust] ``` -------------------------------- ### Setting up CKB Debugger Environment (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Commands to create a project directory, initialize npm, and install necessary CKB SDK and Molecule libraries for the CKB script debugging environment. ```shell $ cd $TOP $ mkdir htlc-runner $ cd htlc-runner $ npm init $ npm install --save @nervosnetwork/ckb-sdk-core $ npm install --save @nervosnetwork/ckb-sdk-utils $ npm install --save molecule-javascript $ npm install --save crc32 ``` -------------------------------- ### Install Make, Sed, Bash, Coreutils - MacOS - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs essential development tools (make, sed, bash, coreutils) on MacOS using Homebrew. These are needed for script development. ```bash brew install make gnu-sed bash coreutils ``` -------------------------------- ### Install Make, Sed, Bash, Coreutils - Linux - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs essential development tools (make, sed, bash, coreutils) on Debian/Ubuntu, Fedora, or ArchLinux using their respective package managers. These are needed for script development. ```bash sudo apt install make sed bash coreutils # Debian/Ubuntu sudo dnf install make sed bash coreutils # Fedora sudo pacman -S make sed bash coreutils # ArchLinux ``` -------------------------------- ### Install Scoop - Windows - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Configures execution policy and installs the Scoop package manager on Windows using PowerShell. Scoop is a prerequisite for installing Rust. ```bash Set-ExecutionPolicy RemoteSigned -Scope CurrentUser iwr -useb get.scoop.sh | iex ``` -------------------------------- ### Install Rust - Windows - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the Rust toolchain on Windows using the Scoop package manager. Rust is needed for CKB script development. ```bash scoop install rust ``` -------------------------------- ### Starting CKB Dev Chain (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This shell script snippet sets up the environment and starts a CKB development chain instance. It navigates directories, exports the CKB binary path, checks the version, initializes a dev chain data directory, and runs the CKB node. ```Shell $ cd $TOP $ export CKB="" $ $CKB --version ckb 0.28.0 (728eff2 2020-02-04) # Block assembler args configured here correspond to the following private key: # 0x0a14c6fd7af6a3f13c9e2aacad80d78968de5d068a342828080650084bf20104 $ $CKB init -c dev -C ckb-data --ba-arg 0x5a7487f529b8b8fd4d4a57c12dc0c70f7958a196 $ $CKB run -C ckb-data ``` -------------------------------- ### Install Rustup - Linux - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the Rust toolchain manager (rustup) on Linux using the official rustup script. Rust is needed for CKB script development. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### offckb Inject Config Response Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Shows the output after running `offckb inject-config`, confirming that the configuration was successfully injected. It also provides examples of how to import and use the generated `offckb.config` object to access script code hashes within the project. ```bash All good. You can now use it in your project like: import offCKB from "offckb.config"; const myScriptCodeHash = offCKB.myScripts['script-name'].codeHash; const omnilockScriptCodeHash = offCKB.systemScripts['omnilock'].codeHash; Check example at https://github.com/nervosnetwork/docs.nervos.org/tree/develop/examples/simple-transfer ``` -------------------------------- ### Install offckb CLI Tool Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/xudt/README.md Installs the `offckb` command-line interface tool globally using npm, which is used for managing CKB devnets. ```Shell npm install -g offckb ``` -------------------------------- ### Creating a Script-Only Project with OffCKB (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Initializes a project focused solely on CKB Script development without a frontend using the `offckb` CLI with the `--script` flag. Replace with the desired project name. ```bash offckb create --script ``` -------------------------------- ### Starting OffCKB Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Starts a local CKB Devnet node using the offckb tool, providing an environment for testing scripts and transactions. ```sh offckb node ``` -------------------------------- ### Build ckb-js-vm Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Build ckb-js-vm, which allows writing and executing Scripts within the CKB-VM using the QuickJS engine. This involves cloning the repository, updating submodules, and building. ```bash git clone https://github.com/nervosnetwork/ckb-js-vm cd ckb-js-vm git submodule update --init make all ``` -------------------------------- ### Install Yarn (≥1.22.0) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Install Yarn, a package manager for JavaScript projects. Version ≥1.22.0 is recommended. This command uses npm for installation. ```bash npm install --global yarn ``` -------------------------------- ### Deploy Scripts to Testnet (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Deploys the built CKB scripts to the Testnet using the `offckb` command-line tool. This command is executed from the frontend workspace. ```sh offckb deploy --network testnet ``` -------------------------------- ### Install Rustup - MacOS - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the Rust toolchain manager (rustup) on MacOS using Homebrew. Rust is needed for CKB script development. ```bash brew install rustup ``` -------------------------------- ### Clone and Run CKB Token Dapp Locally Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/xudt/README.md Clones the repository containing the Dapp example, navigates to the example directory, and starts the application using yarn for local execution. ```Shell git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/xudt yarn && yarn start ``` -------------------------------- ### Install npm (Node.js v20.18.0 LTS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Install npm (Node.js package manager) along with Node.js. Version v20.18.0 LTS is recommended for managing project dependencies. ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install node@20.18.0 ``` ```bash curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs ``` -------------------------------- ### Install CCC Connector - Web Component - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the CKB-CCC connector package for Web Component usage using npm. CCC is used for interacting with CKB. ```bash npm install @ckb-ccc/connector ``` -------------------------------- ### Deploy Scripts to Devnet (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Deploys the built CKB scripts to the Devnet using the `offckb` command-line tool. This command is executed from the frontend workspace. ```sh offckb deploy --network devnet ``` -------------------------------- ### Install Library, Build, and Run CKB Script (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Sequence of shell commands to navigate to the project directory, install the `crc32` npm package, build the script, navigate to the runner directory, and execute the script with debugging enabled, showing the resulting debug output. ```Shell $ cd $TOP/htlc-template $ npm install --save crc32 $ npm run build $ cd $TOP/htlc-runner $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/load0 ../htlc-template/build/duktape.js` DEBUG:: script group: Byte32(0x35ab3d033e66c426573ed4b7ce816e248cb042d908fd8cfe7bba27acb37fb108) DEBUG OUTPUT: c: 0x970dd9a8 DEBUG:: script group: Byte32(0x35ab3d033e66c426573ed4b7ce816e248cb042d908fd8cfe7bba27acb37fb108) DEBUG OUTPUT: 970dd9a8 Run result: Ok(0) ``` -------------------------------- ### Starting Frontend Development Server (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-lock/README.md Navigates into the frontend project directory and runs the standard `npm run dev` command to start the local development server for the Dapp. ```bash cd frontend npm run dev ``` -------------------------------- ### Install offckb CLI Tool Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-transfer/README.md Installs the offckb command-line interface tool globally using npm. This tool is used to start and manage a local CKB development network. ```Shell npm install -g offckb ``` -------------------------------- ### Start CKB Devnet using offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-transfer/README.md Starts a local CKB development network node using the globally installed offckb CLI tool. This provides a local blockchain environment for testing. ```Shell offckb node ``` -------------------------------- ### Install CCC - Custom UI - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the main CKB-CCC JavaScript SDK package for custom UI implementations using npm. CCC is used for interacting with CKB. ```bash npm install @ckb-ccc/ccc ``` -------------------------------- ### Install offckb CLI Tool Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/create-dob/README.md Installs the 'offckb' command-line interface tool globally using npm. This tool is used to easily start and manage a local CKB development network. ```Shell npm install -g offckb ``` -------------------------------- ### Install Homebrew - MacOS - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the Homebrew package manager on MacOS using a curl script. This is a prerequisite for installing other tools like Make, Sed, Bash, Coreutils, and Rust. ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` -------------------------------- ### Run Dapp Example on CKB Testnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/store-data-on-cell/README.md Sets the NETWORK environment variable to 'testnet', changes the current directory to the write-and-read-message example folder, and starts the application configured to connect to the CKB testnet. ```sh export NETWORK=testnet cd write-and-read-message yarn start ``` -------------------------------- ### Navigate to App Directory and Inject offckb Config Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Changes the current directory to the newly created React application folder ('my-cra-dapp') and then runs the `offckb inject-config` command to integrate the offCKB configuration files and settings into the project structure. ```bash cd my-cra-dapp offckb inject-config ``` -------------------------------- ### Install CCC Core - NodeJS - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the core CKB-CCC JavaScript SDK package for Node.js environments using npm. CCC is used for interacting with CKB. ```bash npm install @ckb-ccc/core ``` -------------------------------- ### OffCKB Help Output Example Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx This code block shows an example of the output generated by running `offckb --help`, listing the various commands available within the OffCKB CLI for managing the CKB development environment. ```bash Usage: offckb [options] [command] ckb development network for your first try Options: -V, --version output the version number -h, --help display help for command Commands: create [options] [your-project-name] Create a new dApp from bare templates node [options] [CKB-Version] Use the CKB to start devnet proxy-rpc [options] Start the rpc proxy server clean Clean the devnet data, need to stop running the chain first accounts Print account list info list-hashes [CKB-Version] Use the CKB to list blockchain scripts hashes inject-config Add offckb.config.ts to your frontend workspace sync-scripts Sync scripts json files in your frontend workspace deposit [options] [toAddress] [amountInCKB] Deposit CKB tokens to address, only devnet and testnet transfer [options] [toAddress] [amountInCKB] Transfer CKB tokens to address, only devnet and testnet transfer-all [options] [toAddress] Transfer All CKB tokens to address, only devnet and testnet balance [options] [toAddress] Check account balance, only devnet and testnet deploy [options] Deploy contracts to different networks, only supports devnet and testnet my-scripts [options] Show deployed contracts info on different networks, only supports devnet and testnet config [item] [value] do a configuration action debug [options] CKB Debugger for development system-scripts [options] Output system scripts of the local devnet mol [options] Generate CKB Moleculec binding code for development repl [options] A custom Nodejs REPL environment bundle for CKB. help [command] display help for command ``` -------------------------------- ### Install CKB-SDK-Go Dependency (bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Adds the `ckb-sdk-go` library as a dependency to the Go project using the `go get` command, fetching the specified version (v2) from the repository. ```bash go get -v github.com/nervosnetwork/ckb-sdk-go/v2 ``` -------------------------------- ### Example Output: CKB Initialization Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-testnet-node.mdx Illustrative output showing the result of initializing the CKB directory and configuration files for the testnet. ```bash WARN: Mining feature is disabled because of lacking the block assembler config options. Initialized CKB directory in /PATH/0.115.0 create ckb.toml create ckb-miner.toml ``` -------------------------------- ### Install CCC Connector React - React - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Installs the CKB-CCC connector package specifically for React applications using npm. CCC is used for interacting with CKB. ```bash npm install @ckb-ccc/connector-react ``` -------------------------------- ### Development Server Startup Output (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Shows the expected output in the console after successfully running 'yarn start', indicating that the Docusaurus website is running and the local URL to access it. ```bash [INFO] Starting the development server... [SUCCESS] Docusaurus website is running at: http://localhost:3000/ ``` -------------------------------- ### Setup Project Directory - Lumos - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/lumos.mdx Creates a new directory named `lumos-example`, navigates into it, and initializes a new pnpm project with default settings (`-y`). This sets up the basic project structure. ```Bash mkdir lumos-example cd lumos-example pnpm init -y ``` -------------------------------- ### Starting CKB Miner (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This shell script snippet shows how to start a CKB miner instance connected to the dev chain data directory. It navigates to the project root and executes the `ckb miner` command, specifying the data directory. ```Shell $ cd $TOP $ $CKB miner -C ckb-data ``` -------------------------------- ### Initializing CKB Script Project with offckb (Response) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx This output shows the result of running `offckb create`. It confirms the project name, destination directory, template generation, file movement, and Git initialization, indicating a successful project setup. ```bash ⚠️ Favorite `gh:cryptape/ckb-script-templates` not found in config, using it as a git repository: https://github.com/cryptape/ckb-script-templates.git 🤷 Project Name: spawn-script 🔧 Destination: /tmp/spawn-script ... 🔧 project-name: spawn-script ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/spawn-script`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/spawn-script ``` -------------------------------- ### Start Dapp on CKB Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-transfer/README.md Sets the NETWORK environment variable to 'devnet' to configure the Dapp to connect to a local CKB development network, changes directory to simple-transfer, installs dependencies (if necessary), and starts the Dapp. ```Shell export NETWORK=devnet cd simple-transfer yarn && yarn start ``` -------------------------------- ### Install Clang Compiler (≥v18) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Install the Clang compiler, essential for building CKB Scripts. Version ≥18 is required for compatibility with CKB tools. Instructions cover MacOS, Linux (Debian/Ubuntu, Fedora, Arch), and Windows. ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install llvm@18 ``` ```bash wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 18 && rm llvm.sh # Debian/Ubuntu sudo dnf -y install clang # Fedora sudo pacman --noconfirm -Syu clang # ArchLinux ``` ```bash Set-ExecutionPolicy RemoteSigned -Scope CurrentUser iwr -useb get.scoop.sh | iex scoop install llvm yasm ``` -------------------------------- ### Starting OffCKB REPL Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Starts the offckb Read-Eval-Print Loop (REPL) with the '-r' flag, likely enabling features for interacting with the Devnet and CKB SDK. ```sh offckb repl -r ``` -------------------------------- ### Run CKB Token Dapp on Testnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/xudt/README.md Sets the NETWORK environment variable to 'testnet', navigates to the Dapp directory, and starts the application configured for the CKB testnet. ```Shell export NETWORK=testnet cd xudt yarn start ``` -------------------------------- ### Debug Full CKB Transaction with offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Use this command to debug an entire CKB transaction by providing its hash. The tool verifies all scripts and outputs detailed execution information, including cycle consumption for each script. ```Shell offckb debug ``` -------------------------------- ### Debug Single CKB Script with Local Binary Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Replace the script being debugged with a local binary file for testing purposes. This command requires the transaction hash, the target script specified by --single-script, and the path to the binary file using the --bin option. ```Shell offckb debug --single-script --bin ``` -------------------------------- ### Initialize React App with TypeScript using CRA Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Initializes a new React application named 'my-cra-dapp' using Create React App (CRA) with the TypeScript template. This command sets up the basic project structure and installs necessary dependencies for a TypeScript-based React project. ```bash npx create-react-app my-cra-dapp --template typescript ``` -------------------------------- ### Start CKB Testnet Node Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-testnet-node.mdx Execute the command to start the CKB node and begin syncing with the Pudge Testnet. ```bash ckb run ``` -------------------------------- ### Running Frontend DApp (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/simple-lock.mdx Navigates to the frontend directory, installs Node.js dependencies using `npm i`, and starts the development server for the Next.js application using `npm run dev`. This makes the web interface accessible locally. ```bash cd frontend && npm i && npm run dev ``` ```text > frontend@0.1.0 dev > next dev ▲ Next.js 14.2.3 - Local: http://localhost:3000 - Environments: .env ✓ Starting... ✓ Ready in 1631ms ``` -------------------------------- ### offckb Sync Scripts Response Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Displays the confirmation message after running `offckb sync-scripts`, indicating that the scripts JSON configuration file has been successfully updated within the frontend project. ```bash scripts json config updated. ``` -------------------------------- ### OffCKB Config List Output Example Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx This JSON object shows an example output of the `offckb config list` command, highlighting the structure and key paths for devnet configuration and data. ```json { "devnet": { "rpcUrl": "", "configPath": "~/Library/Application Support/offckb-nodejs/devnet", "dataPath": "~/Library/Application Support/offckb-nodejs/devnet/data" } } ``` -------------------------------- ### Run CKB Token Dapp on Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/xudt/README.md Sets the NETWORK environment variable to 'devnet', navigates to the Dapp directory, and starts the application configured for the local CKB devnet. ```Shell export NETWORK=devnet cd xudt yarn && yarn start ``` -------------------------------- ### Setup CKB-SDK-Go Client (Go) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Demonstrates how to import the necessary RPC package and establish a connection to a CKB node (Testnet, Devnet, or Mainnet) by providing the appropriate URL to the `rpc.Dial` function. ```Go import ( "github.com/nervosnetwork/ckb-sdk-go/v2/rpc" ) testnetURL := "https://testnet.ckb.dev" // Testnet devnetURL := "http://127.0.0.1:8114" // Devnet mainnetURL := "https://mainnet.ckb.dev/rpc" // Mainnet // Connect to Testnet ckbClient, err := rpc.Dial(testnetURL) ``` -------------------------------- ### Starting Devnet with offckb CLI (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/_StartDevnet.mdx This command starts the CKB Devnet using the offckb CLI. It initializes the configuration, downloads necessary binaries if missing, and begins running the CKB node and miner. The output shows the initialization process and node version. ```bash offckb node ``` -------------------------------- ### Sync Deployed Scripts Configuration with offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Executes the `offckb sync-scripts` command in the frontend project's root directory. This command updates the `offckb.config.ts` file with the latest information about the deployed CKB scripts, ensuring the frontend uses the correct script hashes and details. ```bash offckb sync-scripts ``` -------------------------------- ### Verify Installation - Node.js/pnpm - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/lumos.mdx Commands to check the installed versions of Node.js and pnpm in the terminal. Useful for confirming prerequisites are met before starting development. ```Bash node -v pnpm -v ``` -------------------------------- ### Initialize Lumos SDK and Wallets Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This JavaScript snippet shows the initial setup in a Node.js REPL environment using the Lumos SDK. It requires the `@ckb-lumos/lumos` package, initializes the configuration for the testnet, connects to an indexer and RPC endpoint, and defines two wallet objects with addresses and private keys. ```js $ node Welcome to Node.js v20.12.0. Type ".help" for more information. > > const lumos = require("@ckb-lumos/lumos"); > const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); > const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); > lumos.config.initializeConfig(lumos.config.TESTNET); > const wallet = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqvwg2cen8extgq8s5puft8vf40px3f599cytcyd8", privkey: "0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6", }; > const wallet2 = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2prryvze6fhufxkgjx35psh7w70k3hz7c3mtl4d", privkey: "0xace08599f3174f4376ae51fdc30950d4f2d731440382bb0aa1b6b0bd3a9728cd" } ``` -------------------------------- ### Run CKB Script and Start REPL (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Shows the shell command to execute the `runner.js` script using the `repl0` Duktape binary instead of `load0`. This runs the script and then drops into a Duktape REPL (Read-Eval-Print Loop) for interactive debugging and testing. ```Shell $ cd $TOP/htlc-runner $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/repl0 ../htlc-template/build/duktape.js` duk> ``` -------------------------------- ### Starting Development Server (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Starts the local development server for the project, typically configured to run on `http://localhost:3000`, allowing you to view and test the application. ```Bash pnpm run dev ``` -------------------------------- ### Manage OffCKB Network Proxy Configuration Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Provides examples for setting, getting, and removing the network proxy configuration using the OffCKB config commands. ```bash offckb config set proxy > save new settings offckb config get proxy > offckb config rm proxy > save new settings offckb config get proxy > No Proxy. ``` -------------------------------- ### Deploying HTLC Scripts and Testing Unlock (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This comprehensive shell script snippet guides the user through building the HTLC template, making runner scripts executable, deploying necessary scripts to the CKB dev chain, creating an HTLC cell, and demonstrating dry-running unlock transactions using both secret string and timeout methods. Includes example command outputs. ```Shell # Make sure the HTLC script is successfully built first $ cd $TOP/htlc-template $ npm run build # Ensure all scripts are runnable $ cd $TOP/htlc-runner $ chmod +x deploy_scripts.js $ chmod +x create_htlc_cell.js $ chmod +x unlock_via_secret_string.js $ chmod +x unlock_via_timeout.js # Let's first deploy duktape binary and JS scripts $ ./deploy_scripts.js \ ../ckb-duktape/build/load0 \ ../htlc-template/build/duktape.js \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" This method is only for demo, don't use it in production Transaction hash: 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 # Let's create a HTLC cell $ ./create_htlc_cell.js \ ../ckb-duktape/build/load0 \ 0xf30e1e8989fc3a4cb1e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" \ 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947 \ 0xc219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd This method is only for demo, don't use it in production Transaction hash: 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd # To save us the hassle of recreating cells, both unlock executables support # a dry run mode, where we only does full transaction verification, but do not # commit the success ones on chain. # First let's show that we can unlock a HTLC cell given the right secret string # and lock script $ ./unlock_via_secret_string.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" \ "i am a secret" \ true This method is only for demo, don't use it in production Dry run success result: { "cycles": "0xb1acc38" } ``` -------------------------------- ### Cleaning Local CKB Devnet Data with OffCKB (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Removes the local CKB Devnet data directory managed by offCKB. This command is used to reset the Devnet to a fresh state before starting the node again. ```bash offckb clean ``` -------------------------------- ### Setting up Development Environment for CKB WASM Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md These shell commands prepare the development environment by cloning required repositories (AssemblyScript, wabt, WAVM, wavm-aot-generator, ckb-standalone-debugger, ckb-binary-patcher, ckb-c-stdlib) and building necessary tools using npm, cmake, and cargo. This setup is required to follow the examples demonstrating performant WASM on CKB. ```Shell $ export TOP=$(pwd) $ git clone https://github.com/AssemblyScript/assemblyscript.git $ cd assemblyscript $ git checkout b433bc425633c3df6a4a30c735c91c78526a9eb7 $ npm install $ cd $TOP $ git clone --recursive https://github.com/WebAssembly/wabt $ cd wabt $ git checkout bec78eafbc203d81b9a6d1ce81f5a80dd7bf692a $ mkdir build $ cd build $ cmake .. $ cmake --build . $ cd $TOP $ git clone https://github.com/xxuejie/WAVM $ cd WAVM $ git checkout cb35225feeb4ba1b5a9c73cbbdb07f4cace9b359 $ mkdir build $ cd build # Make sure you are using LLVM 9+, you might need to tweak this path depending # on your environment $ cmake .. -DLLVM_DIR=/usr/lib/llvm-9/lib/cmake/llvm $ cmake --build . $ cd $TOP $ git clone https://github.com/xxuejie/wavm-aot-generator $ cd wavm-aot-generator $ git checkout 8c818747eb19494fc9c5e0289810aa7ad484a22e $ cargo build --release $ cd $TOP $ git clone https://github.com/xxuejie/ckb-standalone-debugger $ cd ckb-standalone-debugger $ git checkout 15e8813b8cb886e95e2c81bbee9f26d47a831850 $ cd bins $ cargo build --release $ cd $TOP $ git clone https://github.com/xxuejie/ckb-binary-patcher $ cd ckb-binary-patcher $ git checkout 930f0b468a8f426ebb759d9da735ebaa1e2f98ba $ cd ckb-binary-patcher $ cargo build --release $ cd $TOP $ git clone https://github.com/nervosnetwork/ckb-c-stdlib $ cd ckb-c-stdlib $ git checkout 693c58163fe37d6abd326c537447260a846375f0 ``` -------------------------------- ### Import and Use Deployed Scripts (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Demonstrates how to import the `offckb.config` file and access details of deployed scripts, such as `cellDeps`, `codeHash`, and `hashType`, to construct a CKB `Script` object for use in the frontend dApp. ```typescript import offckb from "offckb.config"; const myScriptDeps: CellDep[] = offCKB.myScripts["YOUR_SCRIPT_NAME"]!.cellDeps; const myScript: Script = { codeHash: offCKB.myScripts["hash-lock"]!.codeHash, hashType: offCKB.myScripts["hash-lock"]!.hashType, args: lockArgs, }; ``` -------------------------------- ### Install Website Dependencies (Yarn/Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Shows the bash command to install the necessary Node.js dependencies for the Docusaurus website using the Yarn package manager. This command should be run inside the 'website' directory. ```bash yarn install ``` -------------------------------- ### Initializing CKB Dev Chain (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This shell script sequence shows how to navigate to the project directory, set the CKB binary path, check the CKB version, initialize a new CKB dev chain configuration with a specific block assembler argument, and finally run the CKB node. ```Shell $ cd $TOP $ export CKB="" $ $CKB --version ckb 0.28.0 (728eff2 2020-02-04) # Block assembler args configured here correspond to the following private key: # 0x0a14c6fd7af6a3f13c9e2aacad80d78968de5d068a342828080650084bf20104 $ $CKB init -c dev -C ckb-data --ba-arg 0x5a7487f529b8b8fd4d4a57c12dc0c70f7958a196 $ $CKB run -C ckb-data ``` -------------------------------- ### Start Dapp on CKB Testnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-transfer/README.md Sets the NETWORK environment variable to 'testnet' to configure the Dapp to connect to the CKB testnet, changes directory to simple-transfer, and starts the Dapp. ```Shell export NETWORK=testnet cd simple-transfer yarn start ``` -------------------------------- ### Add RISC-V Target - Windows - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Adds the riscv64imac-unknown-none-elf target to the Rust toolchain using rustup. This target is required for compiling CKB scripts on Windows. ```bash rustup target add riscv64imac-unknown-none-elf ``` -------------------------------- ### CKB Transaction Runner Script Start (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Starts a Node.js script (runner.js) intended to prepare the transaction skeleton for the CKB debugger. It imports necessary libraries like molecule-javascript, @nervosnetwork/ckb-sdk-utils, and process. ```javascript #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const schema = require('../htlc-template/schema/blockchain-combined.json') const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') ``` -------------------------------- ### Cloning Repository and Navigating Directory (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/simple-lock.mdx Clones the project repository from GitHub and changes the current directory to the simple-lock example folder. This is the first step to set up the project locally. ```bash git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/simple-lock ``` -------------------------------- ### OffCKB Devnet Data Clean Output (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Shows the console output confirming that the local CKB Devnet chain data has been successfully removed by the `offckb clean` command. ```bash Chain data cleaned. ``` -------------------------------- ### Loading Code from GitHub Raw Source via URL Parameter (Example) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/playground.mdx This bash example demonstrates the general format for loading code into the CCC Playground directly from a raw source URL (like GitHub) by appending the '?src=' parameter to the playground's base URL. ```Bash https://live.ckbccc.com/?src=https://raw.githubusercontent.com/your-repo/your-file.ts ``` -------------------------------- ### Install OffCKB CLI via npm Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Installs the OffCKB command-line interface globally using npm, making the `offckb` command available in your terminal for use in any directory. ```bash npm install -g @offckb/cli ``` -------------------------------- ### Run App on Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/create-dob/README.md Sets the NETWORK environment variable to 'devnet', navigates to the Dapp directory, installs dependencies if needed, and starts the application configured for the local CKB development network. ```Shell export NETWORK=devnet cd create-dob yarn && yarn start ``` -------------------------------- ### Installing Project Dependencies (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Installs all required project dependencies listed in the `package.json` file using the pnpm package manager. ```Bash pnpm install ``` -------------------------------- ### Generated C Code from ZetZ Example Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-10.md Presents the C code generated by the ZetZ compiler from the carrot example. It shows that the generated code is clean, efficient, and lacks any runtime overhead related to the theorem proving checks, which are performed at build time. ```C #include #include #include static int ckb_zz_demo_main_load_data(uint64_t const index, uint8_t* const buffer); #include int __attribute__((visibility("default"))) ckb_zz_demo_main_main(); #include static int ckb_zz_demo_main_load_data(uint64_t const index, uint8_t* const buffer); int main() { uint64_t const index = 0; while (true) { uint8_t const buffer[6]; int const ret = ckb_zz_demo_main_load_data(index, buffer); if ((ret == 1)) { break; } if ((memcmp(buffer, "carrot", 6) == 0)) { return -1; } (index++); } return 0; } static int ckb_zz_demo_main_load_data(uint64_t const index, uint8_t* const buffer) { uint64_t l = 6; int const ret = (int)(ckb_load_cell_data(buffer, (&l), 0, index, 2)); return ret; } ``` -------------------------------- ### Add RISC-V Target - MacOS - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Adds the riscv64imac-unknown-none-elf target to the Rust toolchain using rustup. This target is required for compiling CKB scripts on MacOS. ```bash rustup target add riscv64imac-unknown-none-elf ``` -------------------------------- ### Initialize CKB RPC Client (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Demonstrates how to import the `CkbRpcClient` and create an instance connected to a specified CKB node URL (Testnet example shown). Includes example URLs for different networks. ```Rust use ckb_sdk::rpc::CkbRpcClient; let testnet_url = "https://testnet.ckb.dev"; // Testnet let devnet_url = "http://127.0.0.1:8114"; // Devnet let mainnet_url = "https://mainnet.ckb.dev/rpc"; // Mainnet // Connect to Testnet let mut ckb_client = CkbRpcClient::new(testnet_url); ``` -------------------------------- ### View Repository Code Structure (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Displays the main directory structure of the Nervos CKB documentation repository, highlighting the 'website' folder where the Docusaurus site resides and the 'examples' folder. ```bash ├── LICENSE ├── README.md ├── examples └── website ├── build ├── docs ├── docusaurus.config.js ├── node_modules ├── package.json ├── sidebars.js ├── src ├── static ├── tsconfig.json └── yarn.lock ``` -------------------------------- ### Verifying Java and Gradle Installation Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/java.mdx Commands to check the installed versions of Java Development Kit (JDK) and Gradle build automation tool in the terminal. ```Bash java -version gradle -v ``` -------------------------------- ### Add RISC-V Target - Linux - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/installation.mdx Adds the riscv64imac-unknown-none-elf target to the Rust toolchain using rustup. This target is required for compiling CKB scripts on Linux. ```bash rustup target add riscv64imac-unknown-none-elf ``` -------------------------------- ### Get Block Info by Number (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Example using the `CkbRpcClient` to fetch block information for block number 0 and print it as pretty-formatted JSON. ```Rust let block = ckb_client.get_block_by_number(0.into()).unwrap(); println!("block: {}", serde_json::to_string_pretty(&block).unwrap()); ``` -------------------------------- ### Starting offckb Nodejs REPL (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Command and initial output for starting the `offckb` Node.js REPL, which provides an interactive environment for building and sending transactions using the CCC SDK. ```sh offckb repl -r ``` ```sh Welcome to OffCKB REPL! [[ Default Network: devnet, enableProxyRPC: true, CCC SDK: 0.0.16-alpha.3 ]] Type 'help()' to learn how to use. OffCKB > ``` -------------------------------- ### Verify Go Installation (bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Checks the installed version of the Go programming language using the `go version` command in the terminal to confirm it meets the minimum requirement. ```bash go version ``` -------------------------------- ### Loading Specific Example Code from GitHub Raw Source via URL Parameter Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/playground.mdx This bash example provides a concrete URL demonstrating how to load a specific TypeScript file from a GitHub repository's raw source into the CCC Playground using the '?src=' parameter. ```Bash https://live.ckbccc.com/?src=https://raw.githubusercontent.com/sporeprotocol/dob-cookbook/refs/heads/main/examples/dob1/2.nervape-genesis(btcfs_bg_btcfs_icon).ts ``` -------------------------------- ### Install Protobuf via Homebrew (MacOS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Installs the `protoc` binary using Homebrew on MacOS, which is required to compile `ckb-vm-pprof-converter` for CKB-Debugger. ```bash brew install protobuf ``` -------------------------------- ### Create New Go Project (bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Sets up a new directory for the Go project, navigates into it, and initializes a Go module using standard bash commands (`mkdir`, `cd`) and the Go module system (`go mod init`). ```bash mkdir ckb-go-example cd ckb-go-example go mod init ckb-go-example ``` -------------------------------- ### Execute CKB Script and Dump VM State (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md This command executes a CKB script (`dump_load0`) that includes a syscall to dump the current VM state. The state is saved to `dump0.bin`. The output shows the execution details and the total cycles consumed during this initial run, which includes the setup and dumping process. ```shell $ cd $TOP $ RUST_LOG=debug ./runner.rb ckb-duktape/build/dump_load0 ckb-duktape-template/build/duktape.js dump0.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input -d dump0.bin DEBUG:: script group: Byte32(0xb5656359cbcd52cfa68e163cdd217657f0cfc533c909d13a1fdd8032f6b4f1f0) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 20199104 Transfer cycles: 67352, running cycles: 20131752 ``` -------------------------------- ### Install CKB-CLI using Cargo Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ckb-cli.mdx Provides the steps to clone the ckb-cli repository from GitHub and install the tool using Rust's package manager, Cargo. ```Shell git clone https://github.com/nervosnetwork/ckb-cli.git cd ckb-cli cargo install --path . -f --locked ``` -------------------------------- ### Build Lumos and Check Config Manager (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/omnilock.mdx Commands to clone the Lumos repository, install dependencies, build the project, and verify the setup by running the config manager script. ```bash git clone https://github.com/ckb-js/lumos.git cd lumos pnpm install pnpm run build # Check if it is working npx ts-node misc/config-manager.ts ``` -------------------------------- ### Getting Block Information by Hash (Java) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/java.mdx Example using the CKB-SDK-Java client to retrieve block details from the CKB node by providing the block hash. ```Java byte[] blockHash = Numeric.hexStringToByteArray("0x77fdd22f6ae8a717de9ae2b128834e9b2a1424378b5fc95606ba017aab5fed75"); Block block = ckbApi.getBlock(blockHash); System.out.println("Block: " + block); ``` -------------------------------- ### Run CKB Light Client (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/glossary.md This command starts the CKB light client using a specified configuration file (e.g., testnet.toml). It allows syncing with the blockchain by downloading only headers, suitable for resource-constrained environments. ```Shell ckb-light-client run --config-file ./testnet.toml ``` -------------------------------- ### Run Local Development Server (Yarn/Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Provides the bash command to start the local development server for the Docusaurus website using Yarn. This allows previewing changes in a web browser. ```bash yarn start ``` -------------------------------- ### Starting CKB Debugger Runner Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md The beginning of a Node.js script ('runner.js') intended to prepare the transaction skeleton for debugging. It imports necessary libraries like molecule-javascript, @nervosnetwork/ckb-sdk-utils, and process. ```javascript #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const schema = require('../htlc-template/schema/blockchain-combined.json') const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') ``` -------------------------------- ### Install protobuf for ckb-debugger on MacOS (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Installs the protobuf dependency required for compiling ckb-vm-pprof-converter on MacOS using the Homebrew package manager. ```bash brew install protobuf ``` -------------------------------- ### Building and Running CKB Script (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Navigates to the script directory, builds the JavaScript script using npm, navigates to the runner directory, and executes the script using a runner utility, demonstrating the output via debug logs. ```shell $ cd $TOP/htlc-template $ npm run build $ cd $TOP/htlc-runner $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/load0 ../htlc-template/build/duktape.js` ``` -------------------------------- ### Start CKB Light Client Node (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Bash command to execute the CKB light client binary, specifying the logging level for Rust and the path to the configuration file (`mainnet.toml`) to start the node process. ```bash RUST_LOG=info,ckb_light_client=info ./ckb-light-client run --config-file ./mainnet.toml ``` -------------------------------- ### Example: Get Live Cell Information Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ckb-cli.mdx Demonstrates using the `rpc get_live_cell` command to retrieve details about a specific live cell on the blockchain using its transaction hash and output index. ```Shell ckb-cli rpc get_live_cell --tx-hash 0x4ec75b5a8de8d180853d5046760a99285c73283a5dc528f81d6ee056f5335172 --index 0 ``` -------------------------------- ### Start CKB Devnet with Default Version Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Starts a local CKB development network node using the default CKB version configured for OffCKB. The RPC server will be available at http://localhost:8114. ```bash offckb node ``` -------------------------------- ### Example Output: CKB Version Check Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-testnet-node.mdx Illustrative output showing the expected response from the `ckb --version` and `ckb-cli --version` commands. ```bash ckb 0.115.0 (d845cbf 2024-04-01) ``` ```bash ckb-cli 1.8.0-rc1 (cf4159b 2024-03-28) ``` -------------------------------- ### Clone Tutorial Repository Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/create-dob.mdx Provides the necessary bash commands to clone the official Nervos documentation examples repository from GitHub and navigate into the specific directory for the 'create-dob' tutorial. ```bash git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/create-dob ``` -------------------------------- ### Start CKB Devnet with offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/create-dob/README.md Executes the 'offckb node' command to start a local CKB development network instance, which is useful for testing Dapps locally without connecting to a public network. ```Shell offckb node ``` -------------------------------- ### Run CKB Script with Duktape REPL (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Similar to running the debugger, this command navigates to the `htlc-runner` directory and executes the runner script. However, it uses the `repl0` duktape binary instead of `load0`, which causes the script execution to drop into a Duktape REPL after processing the transaction setup. ```Shell $ cd $TOP/htlc-runner $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/repl0 ../htlc-template/build/duktape.js` ``` -------------------------------- ### Generate Molecule Schemas for JavaScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Installs the `moleculec` tool and uses it to generate JSON schema files from a Molecule definition (`htlc.mol`), first for the core schema and then combining it with the blockchain schema for use with `molecule-javascript`. ```shell $ cd $TOP/htlc-template $ cargo install moleculec $ moleculec --language - --format json --schema-file htlc.mol > src/htlc.json $ npx moleculec-js -ns src/htlc.json > src/htlc-combined.json ``` -------------------------------- ### Run CKB VM from Dumped State (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Executes the previously dumped VM state binary (`dump0.bin`) directly using `ckb-standalone-debugger`. This demonstrates loading the pre-initialized state, skipping the initial setup phase and consuming fewer cycles compared to the first execution. ```shell $ RUST_LOG=debug ./runner.rb dump0.bin ckb-duktape-template/build/duktape.js Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input DEBUG:: script group: Byte32(0x51959c6288a1cfba0d7f7dc8c5a90cf9a84bf5b58f1d5ed3b355497d119fba16) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 16249542 Transfer cycles: 96998, running cycles: 16152544 ``` -------------------------------- ### Compiling and Running WASI Example on CKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md This shell script demonstrates the process of compiling a WebAssembly Text (Wast) example using WAVM, generating Ahead-of-Time (AOT) code, linking it with the CKB runtime and WASI ABI, and finally executing the resulting binary on the CKB VM using a runner script. ```Shell $ cd $TOP $ WAVM/build/bin/wavm compile --target-triple riscv64 WAVM/Examples/helloworld.wast helloworld_precompiled.wasm $ wavm-aot-generator/target/release/wavm-aot-generator helloworld_precompiled.wasm helloworld_precompiled $ cat << EOF > helloworld_wavm_main.c #include "helloworld_precompiled_glue.h" #include "abi/ckb_vm_wasi_abi.h" /* main is already generated via wavm-aot-generator */ EOF $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@d28602dba318:/# cd /code root@d28602dba318:/code# riscv64-unknown-elf-gcc -O3 -I ckb-c-stdlib -I wavm-aot-generator -I wabt/wasm2c helloworld_wavm_main.c wavm-aot-generator/abi/riscv64_runtime.S helloworld_precompiled.o -o helloworld_wavm -Wl,-T wavm-aot-generator/abi/riscv64.lds root@d28602dba318:/code# exit exit $ ckb-binary-patcher/target/release/ckb-binary-patcher -i helloworld_wavm -o helloworld_wavm_patched $ RUST_LOG=debug ./runner.rb helloworld_wavm_patched 0x DEBUG:: script group: Byte32(0x86cfac3b49b8f97f913aa5a09d02ad1e5b1ab5be0be793815e9cb714ba831948) DEBUG OUTPUT: Hello World! Run result: Ok(0) Total cycles consumed: 20260 Transfer cycles: 17728, running cycles: 2532 ``` -------------------------------- ### Compiling and Running WASI Example on CKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md This shell script demonstrates the process of compiling a WASI-enabled WebAssembly example (.wast) to RISC-V using WAVM, generating AOT code, compiling a C main file that includes WASI ABI and the generated glue code, running the compilation within a Docker container with the RISC-V toolchain, patching the resulting binary, and finally executing it using a CKB runner script. ```Shell $ cd $TOP $ WAVM/build/bin/wavm compile --target-triple riscv64 WAVM/Examples/helloworld.wast helloworld_precompiled.wasm $ wavm-aot-generator/target/release/wavm-aot-generator helloworld_precompiled.wasm helloworld_precompiled $ cat << EOF > helloworld_wavm_main.c #include "helloworld_precompiled_glue.h" #include "abi/ckb_vm_wasi_abi.h" /* main is already generated via wavm-aot-generator */ EOF $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@d28602dba318:/# cd /code root@d28602dba318:/code# riscv64-unknown-elf-gcc -O3 -I ckb-c-stdlib -I wavm-aot-generator -I wabt/wasm2c helloworld_wavm_main.c wavm-aot-generator/abi/riscv64_runtime.S helloworld_precompiled.o -o helloworld_wavm -Wl,-T wavm-aot-generator/abi/riscv64.lds root@d28602dba318:/code# exit exit $ ckb-binary-patcher/target/release/ckb-binary-patcher -i helloworld_wavm -o helloworld_wavm_patched $ RUST_LOG=debug ./runner.rb helloworld_wavm_patched 0x DEBUG:: script group: Byte32(0x86cfac3b49b8f97f913aa5a09d02ad1e5b1ab5be0be793815e9cb714ba831948) DEBUG OUTPUT: Hello World! Run result: Ok(0) Total cycles consumed: 20260 Transfer cycles: 17728, running cycles: 2532 ``` -------------------------------- ### Install wscat for WebSocket RPC Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/rpcs.mdx Installs the `wscat` command-line tool globally using npm. This tool is required to interact with WebSocket-based RPC endpoints, such as the one provided by a CKB node. ```Shell npm install -g wscat ``` -------------------------------- ### Setting CKB Network Environment Variable (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/README.md This command sets the NETWORK environment variable, allowing you to switch between different CKB networks (devnet, testnet, mainnet) for running dApp examples. ```Shell export NETWORK=testnet # or testnet, mainnet ``` -------------------------------- ### Start CKB Mainnet Node - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-mainnet-node.mdx Starts the CKB node process, connecting it to the mainnet. The node will begin syncing with the network and participating in its operations. ```bash ckb run ``` -------------------------------- ### Running Next.js Development Server (bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-lock/frontend/README.md Provides commands to start the Next.js development server using various package managers like npm, yarn, pnpm, or bun. This allows you to run the application locally for development. ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` -------------------------------- ### Starting Local CKB Devnet Node (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Command to start a local CKB blockchain node using `offckb` for development and testing. ```sh offckb node ``` -------------------------------- ### Set Default CKB Version and Start Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Configures OffCKB to use a specific CKB version (e.g., 0.117.0) as the default for future `offckb node` commands, then immediately starts the development network using this newly set default version. ```bash offckb config set ckb-version 0.117.0 offckb node ``` -------------------------------- ### Initializing CKB Script Project with offckb (Command) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx This command uses the `offckb` tool to initialize a new CKB script project. It creates a directory named `spawn-script` and sets up the necessary files and structure based on a template for developing CKB scripts. ```bash offckb create --script spawn-script ``` -------------------------------- ### Start Next.js dApp Development Server (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/blockchain-networks.mdx Runs the development server for the Next.js dApp. The network is determined by the NEXT_PUBLIC_NETWORK variable set in the .env file. ```bash npm run dev ``` -------------------------------- ### CKB Script with crc32 Usage (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md The JavaScript code for the CKB script (`src/index.js`) demonstrating how to require the installed `crc32` library and use it to calculate the CRC32 hash of a string. It also includes code for deserializing script arguments and using `CKB.debug` for output. ```JavaScript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = new Molecule(schema.declarations[scriptTypeIndex]) // Write your script logic here. const customSchema = require('./htlc-combined.json') const customNames = customSchema.declarations.map(d => d.name) const htlcArgsIndex = customNames.indexOf('HtlcArgs') const htlcArgsType = new Molecule(customSchema.declarations[htlcArgsIndex]) function bytesToHex(b) { return "0x" + Array.prototype.map.call( new Uint8Array(b), function(x) { return ('00' + x.toString(16)).slice(-2) } ).join('') } function hexStringArrayToHexString(a) { let s = "0x"; for (let i = 0; i < a.length; i++) { s = s + a[i].substr(2) } return s } const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) CKB.debug(`c: ${hexStringArrayToHexString(htlcArgs[2][1])}`) const crc32 = require('crc32') CKB.debug(crc32('i am a secret')) ``` -------------------------------- ### Verify Rust and Cargo Installation (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Commands to check the installed versions of the Rust compiler (`rustc`) and the Cargo package manager. ```Bash rustc --version cargo --version ``` -------------------------------- ### Generating Molecule JSON Schema (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Installs the moleculec tool, generates a JSON schema file from the htlc.mol definition, and then uses moleculec-js to combine it with the blockchain schema into a single JSON file for use in JavaScript. ```shell $ cd $TOP/htlc-template $ cargo install moleculec $ moleculec --language - --format json --schema-file htlc.mol > src/htlc.json $ npx moleculec-js -ns src/htlc.json > src/htlc-combined.json ``` -------------------------------- ### Start CKB Devnet Without RPC Proxy Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Starts the local CKB development network node but explicitly skips starting the optional RPC proxy server that normally runs on port 9000. This is useful if you don't need the proxy's features. ```bash offckb node --no-proxy ``` -------------------------------- ### Install CKB-Debugger via Cargo (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Installs the CKB-Debugger command-line tool using the Rust package manager, Cargo. This is the recommended installation method. ```bash cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger ``` -------------------------------- ### Start OffCKB REPL - OffCKB CLI Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Launch the OffCKB interactive Node.js REPL environment. This REPL includes built-in CKB-related variables and functions, making it suitable for simple script testing and development tasks directly in the terminal. ```bash offckb repl --network ``` -------------------------------- ### Run Remix-Vite dApp with Specific Network (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/blockchain-networks.mdx Sets the NETWORK environment variable and starts the Remix-Vite dApp development server. Replace 'devnet' with 'testnet' or 'mainnet' to switch networks. ```bash NETWORK=devnet npm run dev ``` -------------------------------- ### Execute CKB Script from Dumped State (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md This command executes the CKB script directly from the previously dumped VM state (`dump0.bin`). It skips the initial setup phase, resulting in significantly fewer cycles consumed compared to the first execution. The output confirms the successful execution and shows the reduced cycle count. ```shell $ RUST_LOG=debug ./runner.rb dump0.bin ckb-duktape-template/build/duktape.js Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input DEBUG:: script group: Byte32(0x51959c6288a1cfba0d7f7dc8c5a90cf9a84bf5b58f1d5ed3b355497d119fba16) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 16249542 Transfer cycles: 96998, running cycles: 16152544 ``` -------------------------------- ### Clone Repository and Navigate Directory (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/write-message.mdx Provides the necessary bash commands to clone the tutorial repository from GitHub and change the current directory to the specific example project. This is the first step in setting up the development environment. ```bash git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/store-data-on-cell ``` -------------------------------- ### Initialize and Run CKB Full Node (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/glossary.md This command initializes the CKB node configuration for the Mainnet and then starts the CKB full node process. It's used to set up and run a full node that syncs the entire blockchain. ```Shell ckb init --chain Mainnet && ckb run ``` -------------------------------- ### Run Nginx Proxy with Docker Compose (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-public-rpc-node.mdx Starts the Nginx proxy service defined in the docker-compose.yml file in detached mode (-d). This brings up the Nginx container configured to proxy requests to the CKB node. Requires Docker and Docker Compose to be installed and running. ```bash docker-compose up -d ``` -------------------------------- ### Create New Rust Project Directory (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Commands to create a new binary Rust project named `ckb-rust-example` and navigate into its directory. ```Bash cargo new --bin ckb-rust-example cd ckb-rust-example ``` -------------------------------- ### Example CKB Transaction JSON Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/transaction.md Provides a complete JSON example illustrating the structure and fields of a CKB transaction, including version, cell dependencies, header dependencies, inputs, outputs, output data, and witnesses. This example demonstrates the format and typical values for each field. ```JSON { "version": "0x0", "cell_deps": [ { "out_point": { "tx_hash": "0xbd864a269201d7052d4eb3f753f49f7c68b8edc386afc8bb6ef3e15a05facca2", "index": "0x0" }, "dep_type": "dep_group" } ], "header_deps": [ "0xaa1124da6a230435298d83a12dd6c13f7d58caf7853f39cea8aad992ef88a422" ], "inputs": [ { "previous_output": { "tx_hash": "0x8389eba3ae414fb6a3019aa47583e9be36d096c55ab2e00ec49bdb012c24844d", "index": "0x1" }, "since": "0x0" } ], "outputs": [ { "capacity": "0x746a528800", "lock": { "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "args": "0x56008385085341a6ed68decfabb3ba1f3eea7b68", "hash_type": "type" }, "type": null }, { "capacity": "0x1561d9307e88", "lock": { "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "args": "0x886d23a7858f12ebf924baaacd774a5e2cf81132", "hash_type": "type" }, "type": null } ], "outputs_data": [ "0x", "0x" ], "witnesses": ["0x55000000100000005500000055000000410000004a975e08ff99fa000142ff3b86a836b43884b5b46f91b149f7cc5300e8607e633b7a29c94dc01c6616a12f62e74a1415f57fcc5a00e41ac2d7034e90edf4fdf800"] } ``` -------------------------------- ### Start CKB Devnet with Specific Version Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Starts a local CKB development network node using the specified CKB version (e.g., 0.117.0) instead of the default. This allows testing against different CKB node versions. ```bash offckb node 0.117.0 ``` -------------------------------- ### List All OffCKB Configuration Settings Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Shows the command to list all available configuration options and the path to the OffCKB settings JSON file. ```bash offckb config list ``` -------------------------------- ### Run CKB Script with Debugger (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Shows the shell command to execute the `runner.js` script (generated previously) with the compiled `load0` Duktape binary and the target JavaScript script. It sets `RUST_LOG=debug` for detailed output from the debugger and shows example output indicating successful execution. ```Shell $ cd $TOP/htlc-runner $ chmod +x runner.js $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/load0 ../htlc-template/build/duktape.js` DEBUG:: script group: Byte32(0x8209891745eb858abd6f5e53c99b4f101bca221bd150a2ece58a389b7b4f8fa7) DEBUG OUTPUT: [object Object] Run result: Ok(0) ``` -------------------------------- ### Generated C Code from ZetZ Example Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-10.md This C code is the output generated by the ZetZ compiler from the provided ZetZ example. It demonstrates that the compiled code is clean, efficient, and resembles hand-written C, without including any runtime overhead for the static checks performed by the SMT solver during compilation. ```C #include #include #include static int ckb_zz_demo_main_load_data(uint64_t const index, uint8_t* const buffer); #include int __attribute__((visibility("default"))) ckb_zz_demo_main_main(); #include static int ckb_zz_demo_main_load_data(uint64_t const index, uint8_t* const buffer); int main() { uint64_t const index = 0; while (true) { uint8_t const buffer[6]; int const ret = ckb_zz_demo_main_load_data(index, buffer); if ((ret == 1)) { break; } if ((memcmp(buffer, "carrot", 6) == 0)) { return -1; } (index++); } return 0; } static int ckb_zz_demo_main_load_data(uint64_t const index, uint8_t* const buffer) { uint64_t l = 6; int const ret = (int)(ckb_load_cell_data(buffer, (&l), 0, index, 2)); return ret; } ``` -------------------------------- ### Implement Service Logic and Start Server (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/ckb-script-ipc.mdx Implement the defined service trait (`World`) for your server struct (`WorldServer`). The `run_server` function starts the server, entering an infinite loop to handle incoming client requests. The `server()` method is automatically generated by the procedural macro. ```Rust use crate::def::World; use ckb_script_ipc_common::spawn::run_server; struct WorldServer; impl World for WorldServer { fn hello(&mut self, name: String) -> Result { if name == "error" { Err(1) } else { Ok(format!("hello, {}", name)) } } } run_server(WorldServer.server()).map_err(|_| Error::ServerError) ``` -------------------------------- ### Read Network Environment Variable in TypeScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Provides an example TypeScript function `readEnvNetwork` that demonstrates how to read a network environment variable (`process.env.NETWORK`). It includes logic to handle missing or invalid values, defaulting to 'devnet', and returns a type-safe network string ('devnet', 'testnet', or 'mainnet'). This function might need adaptation based on the specific frontend framework's environment handling. ```ts function readEnvNetwork(): "devnet" | "testnet" | "mainnet" { // you may need to update the env method // according to your frontend framework const network = process.env.NETWORK; const defaultNetwork = "devnet"; if (!network) return defaultNetwork; if (!["devnet", "testnet", "mainnet"].includes(network)) { return defaultNetwork; } return network as "devnet" | "testnet" | "mainnet"; } ``` -------------------------------- ### Install CCC Web Component Package Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Installs the CCC connector package for Web Components using npm. This package facilitates wallet connections within web components. ```bash npm install @ckb-ccc/connector ``` -------------------------------- ### Integrating crc32 in CKB Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This JavaScript code snippet, intended for a CKB script running in Duktape, demonstrates how to require and use the `crc32` library. It includes existing logic for deserializing script arguments using Molecule and adds code to calculate the CRC32 hash of a hardcoded string ('i am a secret') and print it using `CKB.debug` for verification. This requires the `crc32` npm package to be installed as a dependency. ```JavaScript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = new Molecule(schema.declarations[scriptTypeIndex]) // Write your script logic here. const customSchema = require('./htlc-combined.json') const customNames = customSchema.declarations.map(d => d.name) const htlcArgsIndex = customNames.indexOf('HtlcArgs') const htlcArgsType = new Molecule(customSchema.declarations[htlcArgsIndex]) function bytesToHex(b) { return "0x" + Array.prototype.map.call( new Uint8Array(b), function(x) { return ('00' + x.toString(16)).slice(-2) } ).join('') } function hexStringArrayToHexString(a) { let s = "0x"; for (let i = 0; i < a.length; i++) { s = s + a[i].substr(2) } return s } const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) CKB.debug(`c: ${hexStringArrayToHexString(htlcArgs[2][1])}`) const crc32 = require('crc32') CKB.debug(crc32('i am a secret')) ``` -------------------------------- ### Run App on Testnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/create-dob/README.md Sets the NETWORK environment variable to 'testnet' for the current shell session, navigates to the Dapp directory, and starts the application configured for the CKB test network. ```Shell export NETWORK=testnet cd create-dob yarn start ``` -------------------------------- ### Clone Repository and Navigate Directory - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/create-token.mdx Clones the nervosnetwork/docs.nervos.org repository and changes the current directory to the xudt example project. This is the first step to set up the development environment for the tutorial. ```bash git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/xudt ``` -------------------------------- ### Install and Run DOB Decoding Server (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/spore-dob-0.mdx Provides bash commands to clone the `dob-decoder-standalone-server` repository and run the server locally for decoding Spore DOBs. ```Bash git clone https://github.com/sporeprotocol/dob-decoder-standalone-server RUST_LOG=dob_decoder_server=debug cargo run ``` -------------------------------- ### OffCKB REPL Welcome Message Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx The initial output displayed upon entering the offckb REPL, confirming the network, proxy status, and SDK version. ```sh Welcome to OffCKB REPL! [[ Default Network: devnet, enableProxyRPC: true, CCC SDK: 0.0.16-alpha.3 ]] Type 'help()' to learn how to use. OffCKB > ``` -------------------------------- ### Verify CKB and CKB-CLI Versions Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-testnet-node.mdx Execute commands to display the installed versions of the CKB node software and the CKB command-line interface. ```bash ckb --version ``` ```bash ckb-cli --version ``` -------------------------------- ### Main function for CKB VM fibonacci example (C) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-4.md Entry point for the C program compiled from WebAssembly via Wasm2C. It parses a command-line argument, initializes the environment, calls the fibonacci function (Z_fibZ_ii), and returns the calculated result. ```C int main(int argc, char** argv) { if (argc < 2) return 2; u8 x = atoi(argv[1]); Z_envZ_abortZ_viiii = &env_abort; init(); u8 result = Z_fibZ_ii(x); return result; } ``` -------------------------------- ### Installing and Running ckb-standalone-debugger (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md Installs the ckb-standalone-debugger from its Git repository using Cargo and then launches it in GDB mode, listening on port 2000, specifying the transaction dump file and the target cell/script group for debugging. ```Bash cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger ckb-debugger --mode gdb --gdb-listen 0.0.0.0:2000 --tx-file carrot.json --cell-index 0 --cell-type output --script-group-type type ``` -------------------------------- ### Response from OFFCKB Project Initialization Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx This output shows the console response after running the 'offckb create' command, indicating the steps taken to set up the new project directory 'sudt-script'. ```bash ⚠️ Favorite `gh:cryptape/ckb-script-templates` not found in config, using it as a git repository: https://github.com/cryptape/ckb-script-templates.git 🤷 Project Name: sudt-script 🔧 Destination: /tmp/sudt-script ... 🔧 project-name: sudt-script ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/sudt-script`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/sudt-script ``` -------------------------------- ### Build and Run CKB Script (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Commands to build the JavaScript CKB script using npm and then execute it using a runner script, demonstrating how to test the script and view its debug output, which includes the deserialized `HtlcArgs` fields. ```shell $ cd $TOP/htlc-template $ npm run build $ cd $TOP/htlc-runner $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/load0 ../htlc-template/build/duktape.js` ``` -------------------------------- ### Clone Repository and Navigate Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/transfer-ckb.mdx These commands clone the official Nervos documentation repository and then change the current directory to the specific example project folder for the simple transfer dApp. ```bash git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org/examples/simple-transfer ``` -------------------------------- ### Initialize and Start Nervos CKB Miner (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/glossary.md This command initializes a Nervos CKB node configured for the Mainnet and then immediately starts the mining process. Mining nodes contribute to network security and consensus by solving computational puzzles and creating new blocks. ```shell ckb init --chain Mainnet && ckb miner ``` -------------------------------- ### Build CKB Standalone Debugger (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md These commands clone the `ckb-standalone-debugger` repository and build the release version of the debugger executable using Cargo. The build is performed within the `bins` subdirectory of the cloned repository. ```Shell $ cd $TOP $ git clone --recursive https://github.com/xxuejie/ckb-standalone-debugger $ cd ckb-standalone-debugger/bins $ cargo build --release ``` -------------------------------- ### Install TypeScript Globally - pnpm - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/lumos.mdx Installs the TypeScript compiler globally on the system using pnpm. This step is optional if TypeScript is not required or managed locally within the project. ```Bash pnpm add -g typescript ``` -------------------------------- ### Install CCC Core Package (NodeJS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Installs the core CCC package for Node.js environments using npm. This package provides the fundamental functionalities of the CCC SDK. ```bash npm install @ckb-ccc/core ``` -------------------------------- ### Install ckb-debugger CLI (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Installs the ckb-standalone-debugger command-line tool using the Rust cargo package manager from its Git repository. Version ≥v0.113.0 is recommended. ```bash cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger ``` -------------------------------- ### Install inferno Tool (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Installs the `inferno` command-line tool, which is required to process profiling data generated by `ckb-debugger` and convert it into a format suitable for visualization, such as SVG for flamegraphs. ```Shell cargo install inferno ``` -------------------------------- ### Install Docker and Docker-Compose (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-public-rpc-node.mdx Installs the necessary Docker and Docker-Compose packages using the apt package manager. These are prerequisites for running the Nginx proxy via Docker Compose. Requires root privileges or sudo. ```bash apt install docker-compose apt install docker ``` -------------------------------- ### Initialize Lumos SDK and Wallets (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Sets up the Lumos SDK in a Node.js environment. It requires the `@ckb-lumos/lumos` package, initializes the configuration for the testnet, connects to a testnet RPC and Indexer, and defines two wallet objects with addresses and private keys. ```js $ node Welcome to Node.js v20.12.0. Type ".help" for more information. > > > const lumos = require("@ckb-lumos/lumos"); > const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); > const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); > lumos.config.initializeConfig(lumos.config.TESTNET); > const wallet = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqvwg2cen8extgq8s5puft8vf40px3f599cytcyd8", privkey: "0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6", }; > const wallet2 = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2prryvze6fhufxkgjx35psh7w70k3hz7c3mtl4d", privkey: "0xace08599f3174f4376ae51fdc30950d4f2d731440382bb0aa1b6b0bd3a9728cd" } ``` -------------------------------- ### Install CCC Custom UI Package Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Installs the CCC package designed for custom UI implementations using npm. Use this package when building a user interface with CCC. ```bash npm install @ckb-ccc/ccc ``` -------------------------------- ### Initialize Native Simulator with ckb-script-templates (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Executes a Makefile target `generate-native-simulator` provided by `ckb-script-templates`. This command initializes the Native Simulator setup for an existing script specified by the `CRATE` variable. ```Shell make generate-native-simulator CRATE= ``` -------------------------------- ### Installing Molecule Schema Compiler (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/tools.mdx Installs the official Molecule schema compiler and code generator (`moleculec`) using the Rust package manager, Cargo. The `--locked` flag ensures a reproducible build. ```bash cargo install moleculec --locked ``` -------------------------------- ### Install CCC React Connector Package Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Installs the CCC connector package specifically for React applications using npm. This package provides React hooks and components for wallet integration. ```bash npm install @ckb-ccc/connector-react ``` -------------------------------- ### Restart OffCKB Devnet Node Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Run this command to start or restart the OffCKB devnet node. It will load the configurations from the specified config path and use the data path for chain storage. ```bash offckb node ``` -------------------------------- ### Getting Help for moleculec (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/tools.mdx Displays the help message for the `moleculec` tool, providing information on available commands, options, and usage. ```bash moleculec --help ``` -------------------------------- ### Example CKB Script with Fibonacci Function (C) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Provides a simple C implementation of a recursive Fibonacci function and a `main` function that calls it, intended as an example CKB Script for debugging purposes. ```C int fib(int n) { if (n == 0 || n == 1) { return n; } else { return fib(n-1) + fib(n-2); } } int main() { if (fib(5) != 5) { return 1; } return 0; } ``` -------------------------------- ### Example Estimate Fee Rate Response (JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/turn-on-fee-estimator.mdx This JSON snippet shows an example response structure returned by the 'estimate_fee_rate' RPC call. The response includes the JSON-RPC version, the request ID, and the 'result' field which contains the estimated fee rate as a hexadecimal string. ```JSON { "jsonrpc": "2.0", "result": "0x3e8", "id": 1 } ``` -------------------------------- ### Build CKB Transaction (Go) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Provides a detailed example of constructing a `types.Transaction` object including cell dependencies, inputs, outputs, output data, and witnesses, and then organizing the relevant scripts into a `transaction.TransactionWithScriptGroups` for signing. ```Go tx := &types.Transaction{ Version: 0, CellDeps: []*types.CellDep{ &types.CellDep{ OutPoint: &types.OutPoint{ TxHash: types.HexToHash("0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37"), Index: 0, }, DepType: types.DepTypeDepGroup, }, }, HeaderDeps: nil, Inputs: []*types.CellInput{ &types.CellInput{ Since: 0, PreviousOutput: &types.OutPoint{ TxHash: types.HexToHash("0x2ff7f46d509c85e1878cf091aef0ba0b89f34f9fea9e8bc868aed2d627490512"), Index: 1, }, }, }, Outputs: []*types.CellOutput{ &types.CellOutput{ Capacity: 10000000000, Lock: &types.Script{ CodeHash: types.HexToHash("0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"), HashType: types.HashTypeType, Args: common.FromHex("0x3f1573b44218d4c12a91919a58a863be415a2bc3") }, Type: nil }, &types.CellOutput{ Capacity: 90000000000, Lock: &types.Script{ CodeHash: types.HexToHash("0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"), HashType: types.HashTypeType, Args: common.FromHex("0xb1d41a1fb06f782cf10a87f3e49e80711af63fcf") }, Type: nil } }, OutputsData: make([][]byte, 2), Witnesses: [][]byte{ common.FromHex("0x55000000100000005500000055000000410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") } } scriptGroups := []*transaction.ScriptGroup{ &transaction.ScriptGroup{ Script: types.Script{ CodeHash: types.HexToHash("0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"), HashType: types.HashTypeType, Args: common.FromHex("0x3f1573b44218d4c12a91919a58a863be415a2bc3") }, GroupType: types.ScriptTypeLock, InputIndices: []uint32{0} } } txWithScriptGroups := &transaction.TransactionWithScriptGroups{ TxView: tx, ScriptGroups: scriptGroups } ``` -------------------------------- ### Example CKB Cell Structure (JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/cell.md Provides a concrete JSON example of a CKB Cell, showing typical values for capacity, lock script (with code_hash, args, hash_type), and a null type script. ```json { "capacity": "0x19995d0ccf", "lock": { "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "args": "0x0a486fb8f6fe60f76f001d6372da41be91172259", "hash_type": "type" }, "type": null } ``` -------------------------------- ### Clone Repository and Navigate (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Provides the bash commands required to clone the 'docs.nervos.org' repository from GitHub and navigate into the 'website' directory where the Docusaurus project is located. ```bash git clone https://github.com/nervosnetwork/docs.nervos.org.git cd docs.nervos.org cd website ``` -------------------------------- ### Start Docker Container for RISC-V Toolchain (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Runs a Docker container containing the CKB RISC-V GNU toolchain, mounting the current directory to /code inside the container for compilation. ```Shell docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash ``` -------------------------------- ### Start Standalone RPC Proxy Server Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Starts the OffCKB RPC proxy server independently in a separate terminal. It forwards requests from the specified port (e.g., 9000) to the CKB node's RPC endpoint (e.g., http://localhost:8114) and can be used for monitoring logs. ```bash offckb proxy-rpc --ckb-rpc --port 9000 --network devnet ``` -------------------------------- ### Build CKB Transaction - OffCKB REPL Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Example demonstrating how to construct, complete inputs and fee, and send a CKB transaction using the built-in CKB Javascript SDK (CCC) within the OffCKB REPL environment. ```javascript let amountInCKB = ccc.fixedPointFrom(63); let tx = ccc.Transaction.from({ outputs: [ { capacity: ccc.fixedPointFrom(amountInCKB), lock: accounts[0].lockScript, }, ], }); let signer = new ccc.SignerCkbPrivateKey(client, accounts[0].privkey); await tx.completeInputsByCapacity(signer); await tx.completeFeeBy(signer, 1000); await mySigner.sendTransaction(tx) ``` -------------------------------- ### Clone Nginx Proxy Configuration (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-public-rpc-node.mdx Clones the ckb-nginx-proxy repository from GitHub. This repository contains the necessary configuration files for setting up the Nginx proxy for the CKB RPC node. Requires git to be installed. ```bash git clone https://github.com/cryptape/ckb-nginx-proxy.git ``` -------------------------------- ### Navigating to Project Directory (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Changes the current directory in the terminal to the newly created project folder, named `my-ckb-app` in this example. ```Bash cd my-ckb-app ``` -------------------------------- ### Load and Parse CKB Script and Arguments (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Demonstrates the core steps within the script to load the current CKB script using a syscall, deserialize its structure using the `Script` Molecule type, extract the arguments field, and prepare it for further deserialization. ```javascript const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) ``` -------------------------------- ### Example Response from estimate_fee_rate RPC Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/fee-estimator.md An example of the JSON response received from the CKB node after calling the `estimate_fee_rate` RPC method. The `result` field contains the estimated fee rate, typically in shannons per transaction weight unit. ```JSON { "jsonrpc": "2.0", "result": "0x3e8", "id": 1 } ``` -------------------------------- ### Loading Witness with ckb_load_witness (C) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/script-group-exe.mdx Example of the CKB syscall `ckb_load_witness` used to load a witness from the transaction. The example shows loading the first witness (index 0) from the transaction inputs using `CKB_SOURCE_INPUT`. Parameters `addr`, `len`, and `offset` control data storage and length. ```C ckb_load_witness(addr, len, offset, 0, CKB_SOURCE_INPUT); ``` -------------------------------- ### Build Website for Deployment (Yarn/Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Provides the bash command to build the static assets for the Docusaurus website, preparing it for deployment to a web server or hosting service. This command should be run inside the 'website' directory. ```bash yarn build ``` -------------------------------- ### Example CKB Address Encoding Parameters and Output Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/ckb-address.mdx This snippet demonstrates the input parameters (code_hash, hash_type, args) used in the CKB address encoding process and shows the resulting full CKB address generated from these components. ```text == full address test == code_hash to encode: 9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8 hash_type to encode: 01 with args to encode: b39bbc0b3673c7d36450bc14cfcdad2d559c6c64 full address generated: ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqdnnw7qkdnnclfkg59uzn8umtfd2kwxceqxwquc4 ``` -------------------------------- ### Compile AssemblyScript to WebAssembly Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-4.md Provides shell commands to clone the AssemblyScript repository, install dependencies using npm, and compile the `fib.ts` source file into an optimized WebAssembly binary (`fib.wasm`) using the AssemblyScript compiler (`asc`). ```Shell $ git clone https://github.com/AssemblyScript/assemblyscript.git $ cd assemblyscript $ npm install $ bin/asc ../fib.ts -b ../fib.wasm -O3 $ cd .. ``` -------------------------------- ### Compile CKB Duktape (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This sequence of shell commands clones the `ckb-duktape` repository and compiles it using a specified Docker image containing the CKB RISC-V GNU toolchain. It mounts the current directory into the container to build the project. ```Shell $ cd $TOP $ git clone --recursive https://github.com/xxuejie/ckb-duktape $ cd ckb-duktape $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@18d4b1952624:/# cd /code root@18d4b1952624:/code# make root@18d4b1952624:/code# exit ``` -------------------------------- ### Build CKB Standalone Debugger (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Provides shell commands to clone the `ckb-standalone-debugger` repository and build it using `cargo build --release`. This compiles the debugger executable required to run and analyze the generated transaction. ```Shell $ cd $TOP $ git clone --recursive https://github.com/xxuejie/ckb-standalone-debugger $ cd ckb-standalone-debugger/bins $ cargo build --release ``` -------------------------------- ### Deploying Callee Script with OffCKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Deploys the 'callee' script binary, located at build/release/callee, to the running offckb Devnet. This script is likely called by the 'caller' script. ```sh offckb deploy --target build/release/callee ``` -------------------------------- ### Build Rust Secp256k1 WASM Example Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Provides shell commands to clone the Secp256k1 test repository, navigate into it, build the Rust project targeting WASM, and convert the resulting WASM file to C code using `wabt/wasm2c`. ```Shell $ cd $TOP $ git clone https://github.com/nervosnetwork/wasm-secp256k1-test $ cd wasm-secp256k1-test $ cargo build --release --target=wasm32-unknown-unknown $ cd $TOP $ wabt/bin/wasm2c wasm-secp256k1-test/target/wasm32-unknown-unknown/release/wasm-secp256k1-test.wasm -o secp.c ``` -------------------------------- ### Compile AssemblyScript to WASM Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-4.md Shell commands to clone the AssemblyScript repository, install dependencies, and compile the fib.ts file into a WebAssembly binary (fib.wasm) with optimizations (-O3). ```Shell git clone https://github.com/AssemblyScript/assemblyscript.git cd assemblyscript npm install bin/asc ../fib.ts -b ../fib.wasm -O3 cd .. ``` -------------------------------- ### Get and Set OffCKB CKB Version Configuration Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Illustrates how to retrieve the current CKB version setting and update it using the OffCKB config commands. ```bash offckb config get ckb-version > 0.113.0 offckb config set ckb-version 0.117.0 offckb config get ckb-version > 0.117.0 ``` -------------------------------- ### Start CKB-CLI Interactive Mode Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ckb-cli.mdx Running the `ckb-cli` command without arguments launches the interactive mode, providing a convenient interface for executing commands. ```Shell ckb-cli ``` -------------------------------- ### Build CKB Light Client from Source (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Provides the necessary bash commands to clone the CKB light client repository from GitHub, navigate into the project directory, and build the release version of the binary using Cargo. This is an alternative to downloading a pre-built binary. ```bash git clone https://github.com/nervosnetwork/ckb-light-client.git cd ckb-light-client cargo build --release ``` -------------------------------- ### Install Lumos SDK - pnpm - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/lumos.mdx Adds the `@ckb-lumos/lumos` package as a dependency to the current project using the pnpm package manager. This makes the Lumos library available for use in the project. ```Bash pnpm add @ckb-lumos/lumos ``` -------------------------------- ### Implementing Carrot Example in ZetZ Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-10.md Demonstrates a simple smart contract logic in ZetZ for the CKB VM. It defines a function `load_data` to load cell data and a `main` function that iterates through cells, checking for a specific value ("carrot") using `memcmp`. It highlights the `where` clause for static verification. ```ZetZ using as ckb using ::{memcmp}; fn load_data(u64 index, u8 mut * buffer) -> int where len(buffer) >= 6 { u64 mut l = 6; int ret = asckb::ckb_load_cell_data(buffer, &l, 0, index, 2); return ret; } export fn main () -> int { u64 index = 0; while true { u8 buffer[6]; int ret = load_data(index, buffer); if ret == 1 { break; } if memcmp(buffer, "carrot", 6) == 0 { return -1; } index++; } return 0; } ``` -------------------------------- ### Initialize RPC Client - Lumos - TypeScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/lumos.mdx Imports the `RPC` class from Lumos and demonstrates how to create an RPC client instance. It shows example URLs for connecting to Testnet, Devnet, and Mainnet, and connects to the Testnet URL to interact with a CKB node. ```TypeScript import { RPC } from "@ckb-lumos/lumos"; const TESTNET_RPC_URL = "https://testnet.ckb.dev"; // Testnet const DEVNET_RPC_URL = "http://127.0.0.1:8114"; // Devnet const MAINNET_RPC_URL = "https://mainnet.ckb.dev/rpc"; // Mainnet // Connect to Testnet const rpc = new RPC(TESTNET_RPC_URL); ``` -------------------------------- ### Serializing table MixedType Example (Hex Bytes) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx This snippet shows the serialized byte representation of a `table MixedType` instance with specific values. It illustrates the serialization format for `table` types, including the full size, offsets for each field, and the serialized bytes of the fields themselves. ```bash # the full size is 43 (0x2b) bytes 2b 00 00 00 # five offsets (20 bytes in total) 18 00 00 00, 1c 00 00 00, 1d 00 00 00, 21 00 00 00, 24 00 00 00 # five items (19 bytes in total) 00 00 00 00 ab 23 01 00 00 45 67 89 03 00 00 00, ab cd ef ``` -------------------------------- ### Starting CKB Debugger with Transaction File (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md This bash command launches the ckb-debugger tool. It specifies the transaction file to debug ("duktape.json"), the cell index (0), the cell type (output), and the script group type (type). This command starts the debugger and presents a duk> prompt for interacting with the script environment. Requires the ckb-debugger tool and the specified transaction file. ```Bash ckb-debugger --tx-file duktape.json --cell-index 0 --cell-type output --script-group-type type duk> ``` -------------------------------- ### Compile CKB Script with Docker (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Demonstrates compiling a CKB script (`carrot.c`) into a RISC-V executable (`carrot`) using a pre-built Docker image containing the necessary GCC toolchain. It shows listing files, running the docker container, navigating inside, compiling, exiting, and verifying the output file. ```bash $ ls carrot.c ckb_consts.h ckb_syscalls.h $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash root@dc2c0c209dcd:/# cd /code root@dc2c0c209dcd:/code# riscv64-unknown-elf-gcc -Os carrot.c -o carrot root@dc2c0c209dcd:/code# exit exit $ ls carrot* carrot.c ckb_consts.h ckb_syscalls.h ``` -------------------------------- ### Start Devnet and Stop Instruction Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Initiates the local CKB development network node. The accompanying comment provides instructions on how to stop the running node process, typically by pressing Ctrl+C in the terminal where it's running. ```bash offckb node # Once started, press Ctrl+C to stop the node ``` -------------------------------- ### Run Duktape Bytecode Directly on CKB (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md Shows how to execute the previously generated Duktape bytecode (`script.bin`) directly using the `runner.rb` script. This command simulates running the smart contract with the bytecode loaded, allowing for measurement of cycle consumption. ```Shell $ RUST_LOG=debug ./runner.rb dump0.bin script.bin ``` -------------------------------- ### Compile JS to Binary with CKB-Debugger (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Compiles the `fib.js` script into a binary (`fib.bc`) using `ckb-debugger` and `ckb-js-vm`, filtering output to get the binary content. ```sh ckb-debugger --read-file js/fib.js --bin deps/ckb-js-vm -- -c | awk '/Run result: 0/{exit} {print}' | xxd -r -p > js/build/fib.bc ``` -------------------------------- ### Creating a New Java Project with Gradle Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/java.mdx Commands to create a new directory for the project, navigate into it, and initialize a new Gradle project structure. ```Bash mkdir ckb-java-example cd ckb-java-example gradle init ``` -------------------------------- ### Deploying and Testing HTLC Scripts (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This comprehensive shell script sequence outlines the steps to build the HTLC script, make the runner executables runnable, deploy the duktape binary and JS scripts to the chain, create an HTLC cell, and finally test unlocking the cell using both the correct secret string (dry run success) and an invalid one (implied failure). ```Shell # Make sure the HTLC script is successfully built first $ cd $TOP/htlc-template $ npm run build # Ensure all scripts are runnable $ cd $TOP/htlc-runner $ chmod +x deploy_scripts.js $ chmod +x create_htlc_cell.js $ chmod +x unlock_via_secret_string.js $ chmod +x unlock_via_timeout.js # Let's first deploy duktape binary and JS scripts $ ./deploy_scripts.js \ ../ckb-duktape/build/load0 \ ../htlc-template/build/duktape.js \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" This method is only for demo, don't use it in production Transaction hash: 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 # Let's create a HTLC cell $ ./create_htlc_cell.js \ ../ckb-duktape/build/load0 \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e006ad0ce8eac07947 \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" \ 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947 \ 0xc219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd This method is only for demo, don't use it in production Transaction hash: 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd # To save us the hassle of recreating cells, both unlock executables support # a dry run mode, where we only does full transaction verification, but do not # commit the success ones on chain. # First let's show that we can unlock a HTLC cell given the right secret string # and lock script $ ./unlock_via_secret_string.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" \ "i am a secret" \ true This method is only for demo, don't use it in production Dry run success result: { "cycles": "0xb1acc38" } ``` -------------------------------- ### Loading Code from Nostr Share Link via URL Parameter Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/playground.mdx This bash example illustrates how to load code that has been shared via the Nostr protocol into the CCC Playground using a URL with the '?src=nostr:...' parameter. ```Bash https://live.ckbccc.com/?src=nostr:nevent1qqsx9g2fyamqm65tmap0upjnyum0232pzysng3dkaz5sjl92mm5dmmspzemhxue69uhhyetvv9ujumn0wd68ytnzv9hxgqg4waehxw309ac82unsd3jhyetvv9ujucm0d5q32amnwvaz7tmjv4kxz7fwdehhxarj9ehx2aqpz3mhxue69uhkummnw3ezummcw3ezuer9wcq3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k79fzrjp ``` -------------------------------- ### Get Block Information (Go) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Shows how to call the `GetBlock` JSON-RPC method on the CKB client to retrieve details for a specific block using its hash. It requires a `context.Context` and the block hash as input. ```Go block, err := ckbClient.GetBlock(context.Background(), types.HexToHash("0x77fdd22f6ae8a717de9ae2b128834e9b2a1424378b5fc95606ba017aab5fed75")) ``` -------------------------------- ### Configuring Fee Estimator Algorithm (TOML) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/turn-on-fee-estimator.mdx This snippet shows how to specify the desired fee estimation algorithm within the [fee_estimator] section of the ckb.toml configuration file. The 'WeightUnitsFlow' algorithm is selected in this example as one of the available options. ```TOML [fee_estimator] # Specifies the fee estimate algorithm. Current options: ConfirmationFraction, WeightUnitsFlow. algorithm = "WeightUnitsFlow" ``` -------------------------------- ### Compile CKB Duktape (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Provides shell commands to clone the `ckb-duktape` repository, navigate into it, and compile the project using `make` within a specified Docker container environment (`nervos/ckb-riscv-gnu-toolchain`). This step is necessary to obtain the Duktape binary used by the runner script. ```Shell $ cd $TOP $ git clone --recursive https://github.com/xxuejie/ckb-duktape $ cd ckb-duktape $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@18d4b1952624:/# cd /code root@18d4b1952624:/code# make root@18d4b1952624:/code# exit ``` -------------------------------- ### Loading and Deserializing CKB Script and Args (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Loads the necessary Molecule schemas (blockchain and custom htlc), defines helper functions for converting bytes to hex strings, loads the current CKB script using a syscall, extracts its arguments, and deserializes the arguments using the HtlcArgs schema. ```javascript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = new Molecule(schema.declarations[scriptTypeIndex]) // Write your script logic here. const customSchema = require('./htlc-combined.json') const customNames = customSchema.declarations.map(d => d.name) const htlcArgsIndex = customNames.indexOf('HtlcArgs') const htlcArgsType = new Molecule(customSchema.declarations[htlcArgsIndex]) function bytesToHex(b) { return "0x" + Array.prototype.map.call( new Uint8Array(b), function(x) { return ('00' + x.toString(16)).slice(-2) } ).join('') } function hexStringArrayToHexString(a) { let s = "0x"; for (let i = 0; i < a.length; i++) { s = s + a[i].substr(2) } return s } const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) CKB.debug(`a: ${hexStringArrayToHexString(htlcArgs[0][1])}`) CKB.debug(`b: ${hexStringArrayToHexString(htlcArgs[1][1])}`) CKB.debug(`c: ${hexStringArrayToHexString(htlcArgs[2][1])}`) ``` -------------------------------- ### Import and Use Deployed Scripts in Frontend Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Example TypeScript code showing how to import the deployed script details from the generated `offckb.config.ts` file and construct `CellDep` and `Script` objects for use in a frontend dApp. ```typescript import offckb from "offckb.config"; const myScriptDeps: CellDep[] = offCKB.myScripts["YOUR_SCRIPT_NAME"]!.cellDeps; const myScript: Script = { codeHash: offCKB.myScripts["hash-lock"]!.codeHash, hashType: offCKB.myScripts["hash-lock"]!.hashType, args: lockArgs, }; ``` -------------------------------- ### Loading and Parsing CKB Script and Args (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Loads the current CKB script using the CKB syscall `CKB.load_script(0)`, converts the raw bytes to a hex string, deserializes the script structure using the Molecule 'Script' type, and extracts the arguments field. ```javascript const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) ``` -------------------------------- ### Generate Duktape Bytecode and Run on CKB (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md Demonstrates generating Duktape bytecode from a JavaScript source file using the `dump_bytecode` tool, then executing the generated bytecode on the CKB VM via the `runner.rb` script and debugger. This shows the initial step of preparing and running the bytecode for performance testing. ```Shell $ cd $TOP $ ckb-duktape/build/dump_bytecode ckb-duktape-template/build/duktape.js script.bin $ RUST_LOG=debug ./runner.rb ckb-duktape/build/dump_load0 script.bin dump0.bin ``` -------------------------------- ### Initial CKB Duktape Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md The default content of the `src/index.js` file in the CKB Duktape template. It demonstrates how to import the Molecule library and a blockchain schema, extract script type information, and includes a placeholder for custom script logic. ```JavaScript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = schema.declarations[scriptTypeIndex] // Write your script logic here. CKB.debug(scriptType) ``` -------------------------------- ### Running Duktape Bytecode on CKB VM (Alternative Runner) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md This snippet shows executing the previously generated Duktape bytecode (`dump0.bin`) on the CKB VM using `runner.rb` with a different setup (implied by the command line arguments). It includes the output showing the execution command, debug information, run result, and total cycles consumed (5289852). This demonstrates the reduced cycle consumption when running bytecode compared to source or potentially a different bytecode loading method. ```Shell $ RUST_LOG=debug ./runner.rb dump0.bin script.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input DEBUG:: script group: Byte32(0x51959c6288a1cfba0d7f7dc8c5a90cf9a84bf5b58f1d5ed3b355497d119fba16) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 5289852 Transfer cycles: 96998, running cycles: 5192854 ``` -------------------------------- ### Deploying Caller Script with OffCKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Deploys the 'caller' script binary, located at build/release/caller, to the running offckb Devnet. This makes the script available for use in transactions. ```sh offckb deploy --target build/release/caller ``` -------------------------------- ### Defining a 3-byte Array (Molecule Schema) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Defines a fixed-size array type named `Byte3` that contains exactly 3 `byte` elements. The example shows how the values `01`, `02`, `03` are serialized directly as `01 02 03` due to the fixed size and consecutive storage. ```Molecule Schema array Byte3 [byte; 3]; ``` -------------------------------- ### View Wallet Generation Output - Console - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/lumos.mdx Shows example console output from running the `wallet.ts` script, displaying the generated private key and the corresponding CKB address. Note that the actual values will differ each time the script is run. ```Bash privateKey: 0x9ab62c912c48d615a030318af514758e8c7b9f03d37a95dd1b89e775b669e0c3 address: ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq0820lwy5m5uqnhpap2h0kms9ta3u3pp2ss889v4 ``` -------------------------------- ### Defining a Struct with a Single Byte Field (Molecule Schema) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Defines a fixed-size struct type named `OnlyAByte` with a single field `f1` of type `byte`. Structs with fixed-size fields are also fixed-size. The example shows a byte value `ab` serialized directly as `ab`. ```Molecule Schema struct OnlyAByte { f1: byte } ``` -------------------------------- ### Test CKB Script With Forbidden Data (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx This Rust test function `test_carrot_attack` simulates a CKB transaction to verify a script that forbids data starting with "carrot". It deploys the script and an always-success lock script, constructs a transaction with inputs and outputs. The intention is to set output data that *does* start with "carrot" to test the script's rejection logic, although the provided snippet is incomplete and cuts off before the output data is fully defined and the verification is called. ```Rust #[test] fn test_carrot_attack() { // deploy contract let mut context = Context::default(); let loader = Loader::default(); let carrot_bin = loader.load_binary("carrot"); let carrot_out_point = context.deploy_cell(carrot_bin); let carrot_cell_dep = CellDep::new_builder() .out_point(carrot_out_point.clone()) .build(); // prepare scripts let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); let lock_script = context .build_script(&always_success_out_point.clone(), Default::default()) .expect("script"); let lock_script_dep = CellDep::new_builder() .out_point(always_success_out_point) .build(); // prepare cell deps let cell_deps: Vec = vec![lock_script_dep, carrot_cell_dep]; // prepare cells let input_out_point = context.create_cell( CellOutput::new_builder() .capacity(1000u64.pack()) .lock(lock_script.clone()) .build(), Bytes::new(), ); let input = CellInput::new_builder() .previous_output(input_out_point.clone()) .build(); let type_script = context .build_script(&carrot_out_point, Bytes::new()) .expect("script"); let outputs = vec![ CellOutput::new_builder() .capacity(500u64.pack()) .lock(lock_script.clone()) .type_(Some(type_script.clone()).pack()) .build(), CellOutput::new_builder() .capacity(500u64.pack()) .lock(lock_script) .build(), ``` -------------------------------- ### Defining an Array of Two Uint32s (Molecule Schema) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Defines a fixed-size array type named `TwoUint32` that contains exactly 2 elements of the previously defined `Uint32` type. The example shows two 32-bit integers, `0x01020304` and `0xabcde` (represented as `0x000abcde`), serialized consecutively in little-endian format. ```Molecule Schema array TwoUint32 [Uint32; 2]; ``` -------------------------------- ### Debug Single CKB Cell Script with offckb Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/quick-start.mdx Debug a specific lock or type script within a transaction by specifying the transaction hash and the target script using the --single-script option. The option format is []., e.g., "input[0].lock". ```Shell offckb debug --single-script ``` -------------------------------- ### Response: Initialize CKB Script Project - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx Expected output when running the `create-ckb-scripts` command. It shows the template generation process and the successful creation of the new project directory. ```Bash ⚠️ Favorite `gh:cryptape/ckb-script-templates` not found in config, using it as a git repository: https://github.com/nervosnetwork/ckb-script-templates.git 🤷 Project Name: my-first-contract-workspace 🔧 Destination: /tmp/my-first-contract-workspace ... 🔧 project-name: my-first-contract-workspace ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/my-first-contract-workspace`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/my-first-contract-workspace ``` -------------------------------- ### Prepare CKB Transaction with Duktape and JS Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This Node.js script reads the Duktape binary and a user-provided JavaScript script, calculates their Blake2b hashes, and generates a `tx.json` file. This file is formatted based on a `skeleton.json` template, embedding the Duktape binary, the JS script, and their hashes for use with the CKB debugger. It requires `fs` and a `utils` module (presumably from a CKB library) and expects paths to the Duktape binary and JS script as command-line arguments. ```JavaScript const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 4) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const duktape_binary = fs.readFileSync(process.argv[2]) const duktape_hash = blake2b(duktape_binary) const js_script = fs.readFileSync(process.argv[3]) const data = fs.readFileSync('skeleton.json', 'utf8'). replace("@DUKTAPE_HASH", utils.bytesToHex(duktape_hash)). replace("@SCRIPT_CODE", utils.bytesToHex(js_script)). replace("@DUKTAPE_CODE", utils.bytesToHex(duktape_binary)) fs.writeFileSync('tx.json', data) const resolved_tx = JSON.parse(data) const json_lock_script = resolved_tx.mock_info.inputs[0].output.lock const lock_script = { codeHash: json_lock_script.code_hash, hashType: json_lock_script.hash_type, args: json_lock_script.args } const lock_script_hash = blake2b(utils.hexToBytes(utils.serializeScript(lock_script))) console.log(`../ckb-standalone-debugger/bins/target/release/ckb-debugger -g lock -h ${utils.bytesToHex(lock_script_hash)} -t tx.json`) ``` -------------------------------- ### Test CKB Script Without Forbidden Data (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx This Rust test function `test_no_carrot` simulates a CKB transaction to verify a script that forbids data starting with "carrot". It deploys the script and an always-success lock script, constructs a transaction with inputs and outputs, and sets output data that does *not* start with "carrot". The test then verifies the transaction using `ckb_testtool`, expecting it to pass, demonstrating the script correctly allows transactions without the forbidden data. ```Rust // Include your tests here // See https://github.com/xxuejie/ckb-native-build-sample/blob/main/tests/src/tests.rs for examples use super::*; use ckb_testtool::{ builtin::ALWAYS_SUCCESS, ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*}, context::Context, }; const MAX_CYCLES: u64 = 10_000_000; #[test] fn test_no_carrot() { // deploy contract let mut context = Context::default(); let loader = Loader::default(); let carrot_bin = loader.load_binary("carrot"); let carrot_out_point = context.deploy_cell(carrot_bin); let carrot_cell_dep = CellDep::new_builder() .out_point(carrot_out_point.clone()) .build(); // prepare scripts let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); let lock_script = context .build_script(&always_success_out_point.clone(), Default::default()) .expect("script"); let lock_script_dep = CellDep::new_builder() .out_point(always_success_out_point) .build(); // prepare cell deps let cell_deps: Vec = vec![lock_script_dep, carrot_cell_dep]; // prepare cells let input_out_point = context.create_cell( CellOutput::new_builder() .capacity(1000u64.pack()) .lock(lock_script.clone()) .build(), Bytes::new(), ); let input = CellInput::new_builder() .previous_output(input_out_point.clone()) .build(); let type_script = context .build_script(&carrot_out_point, Bytes::new()) .expect("script"); let outputs = vec![ CellOutput::new_builder() .capacity(500u64.pack()) .lock(lock_script.clone()) .type_(Some(type_script.clone()).pack()) .build(), CellOutput::new_builder() .capacity(500u64.pack()) .lock(lock_script) .build(), ]; // prepare output cell data let outputs_data = vec![Bytes::from("apple"), Bytes::from("tomato")]; // build transaction let tx = TransactionBuilder::default() .cell_deps(cell_deps) .input(input) .outputs(outputs) .outputs_data(outputs_data.pack()) .build(); let tx = tx.as_advanced_builder().build(); // run let cycles = context .verify_tx(&tx, MAX_CYCLES) .expect("pass verification"); println!("consume cycles: {}", cycles); } ``` -------------------------------- ### Defining a Struct with Byte and Uint32 Fields (Molecule Schema) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Defines a fixed-size struct type named `ByteAndUint32` with two fields: `f1` of type `byte` and `f2` of type `Uint32`. The example shows a byte `ab` and a 32-bit integer `0x010203` (represented as `0x00010203`) serialized consecutively, with the integer in little-endian format. ```Molecule Schema struct ByteAndUint32 { f1: byte, f2: Uint32 } ``` -------------------------------- ### Verify CKB and CKB-CLI Versions - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-mainnet-node.mdx Executes commands to display the installed versions of the CKB node software and the CKB command-line interface. This confirms the binaries are accessible and shows their versions. Expected output format: ckb 0.115.0 (d845cbf 2024-04-01) ckb-cli 1.8.0-rc1 (cf4159b 2024-03-28) ```bash ckb --version ckb-cli --version ``` -------------------------------- ### Defining a 4-byte Array for Uint32 (Molecule Schema) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Defines a fixed-size array type named `Uint32` that contains exactly 4 `byte` elements. This type is commonly used to represent a 32-bit unsigned integer. The example shows the integer `0x01020304` serialized in little-endian format as `04 03 02 01`. ```Molecule Schema array Uint32 [byte; 4]; ``` -------------------------------- ### Build Lumos JavaScript/TypeScript SDK Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/omnilock.mdx Provides a sequence of bash commands necessary to clone the Lumos repository, install its dependencies using pnpm, build the project, and verify the build by running a configuration manager script. ```Bash # Build Lumos git clone https://github.com/ckb-js/lumos.git cd lumos pnpm install pnpm run build # Check if it is working npx ts-node misc/config-manager.ts ``` -------------------------------- ### Import CCC Core Object Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Imports the main `ccc` object from the installed CCC package. This object encapsulates most of the SDK's functionalities. ```tsx import { ccc } from "@ckb-ccc/"; ``` -------------------------------- ### Defining Skills and Skill Sets Molecule C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/example-role-playing-game.mdx Defines individual skills as optional types (`option`) based on `SkillLevel`, groups all possible skills into a `union` called `Skill`, and defines a dynamic list of learned skills using a `vector` called `Skills`. Imports the `common/basic_types` schema. ```c import common/basic_types; // We define several skills. // None means the role can learn a skill but he/she doesn't learn it. option ArmorLight (SkillLevel); option ArmorHeavy (SkillLevel); // only Fighter can learn this option ArmorShields (SkillLevel); // only Fighter can learn this option WeaponSwords (SkillLevel); // only Mage can't learn this option WeaponBows (SkillLevel); // only Ranger can learn this option WeaponBlunt (SkillLevel); option Dodge (SkillLevel); option PickLocks (SkillLevel); option Mercantile (SkillLevel); option Survival (SkillLevel); // ... omit other skills ... // Any skill which is defined above. union Skill { ArmorLight, ArmorHeavy, ArmorShields, WeaponSwords, WeaponBows, WeaponBlunt, Dodge, PickLocks, Mercantile, Survival, // ... omit other skills ... } // A hero can learn several skills. The size of learned skills is dynamic. vector Skills ; ``` -------------------------------- ### Loading Script with ckb_load_script (C) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/script-group-exe.mdx Example of the CKB syscall `ckb_load_script` used within a script to load its own code. The parameters `addr`, `len`, and `offset` control where the data is stored and how much is read. ```C ckb_load_script(addr, len, offset) ``` -------------------------------- ### Prepare CKB Transaction JSON with Duktape and JS Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This script reads a Duktape binary and a JavaScript script, computes their Blake2b hashes, and embeds them along with the Duktape binary content into a skeleton transaction JSON file. It then calculates the hash of the lock script defined in the generated JSON and prints a command to execute the CKB debugger with the transaction file and lock script hash. Requires `fs` and `utils` modules. ```JavaScript const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 4) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const duktape_binary = fs.readFileSync(process.argv[2]) const duktape_hash = blake2b(duktape_binary) const js_script = fs.readFileSync(process.argv[3]) const data = fs.readFileSync('skeleton.json', 'utf8'). replace("@DUKTAPE_HASH", utils.bytesToHex(duktape_hash)). replace("@SCRIPT_CODE", utils.bytesToHex(js_script)). replace("@DUKTAPE_CODE", utils.bytesToHex(duktape_binary)) fs.writeFileSync('tx.json', data) const resolved_tx = JSON.parse(data) const json_lock_script = resolved_tx.mock_info.inputs[0].output.lock const lock_script = { codeHash: json_lock_script.code_hash, hashType: json_lock_script.hash_type, args: json_lock_script.args } const lock_script_hash = blake2b(utils.hexToBytes(utils.serializeScript(lock_script))) console.log(`../ckb-standalone-debugger/bins/target/release/ckb-debugger -g lock -h ${utils.bytesToHex(lock_script_hash)} -t tx.json`) ``` -------------------------------- ### Build Go Project (bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Compiles the Go project source code into an executable binary in the project root directory using the `go build` command. ```bash go build ``` -------------------------------- ### BTC Locking Script Example (Sum to 8) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/ckb-vs-btc.mdx A simple Bitcoin locking script (`scriptPubKey`) that requires the sum of two numbers provided in the unlocking script to equal 8 for the transaction to be valid. ```Bitcoin Script OP_ADD <8> OP_EQUAL ``` -------------------------------- ### Rust SDK Omnilock Transaction Example Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/omnilock.mdx Demonstrates the process of creating, signing, and sending a transaction utilizing the Omnilock Script with the Nervos Rust SDK. It includes steps for setting up the transaction builder, adding outputs, configuring Omnilock context, signing the transaction with a private key, and broadcasting it to the network. ```Rust use ckb_sdk::{ constants::ONE_CKB, transaction::{ builder::{CkbTransactionBuilder, SimpleTransactionBuilder}, handler::{omnilock, HandlerContexts}, input::InputIterator, signer::{SignContexts, TransactionSigner}, TransactionBuilderConfiguration, }, unlock::OmniLockConfig, Address, CkbRpcClient, NetworkInfo, }; use ckb_types::{ h256, packed::CellOutput, prelude::{Builder, Entity, Pack}, }; use std::{error::Error as StdErr, str::FromStr}; fn main() -> Result<(), Box> { let network_info = NetworkInfo::testnet(); let sender = Address::from_str("ckt1qrejnmlar3r452tcg57gvq8patctcgy8acync0hxfnyka35ywafvkqgqgpy7m88v3gxnn3apazvlpkkt32xz3tg5qq3kzjf3")?; let receiver = Address::from_str("ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqv5dsed9par23x4g58seaw58j3ym5ml2hs8ztche")?; let configuration = TransactionBuilderConfiguration::new_with_network(network_info.clone())?; let iterator = InputIterator::new_with_address(&[sender.clone()], configuration.network_info()); let mut builder = SimpleTransactionBuilder::new(configuration, iterator); let output = CellOutput::new_builder() .capacity((128 * ONE_CKB).pack()) .lock((&receiver).into()) .build(); builder.add_output_and_data(output.clone(), ckb_types::packed::Bytes::default()); builder.set_change_lock((&sender).into()); let omni_cfg = OmniLockConfig::from_addr(&sender).unwrap(); let context = omnilock::OmnilockScriptContext::new(omni_cfg.clone(), network_info.url.clone()); let mut contexts = HandlerContexts::default(); contexts.add_context(Box::new(context) as Box<_>); let mut tx_with_groups = builder.build(&mut contexts)?; let json_tx = ckb_jsonrpc_types::TransactionView::from(tx_with_groups.get_tx_view().clone()); println!("tx: {}", serde_json::to_string_pretty(&json_tx).unwrap()); let private_key = h256!("0x6c9ed03816e3111e49384b8d180174ad08e29feb1393ea1b51cef1c505d4e36a"); TransactionSigner::new(&network_info).sign_transaction( &mut tx_with_groups, &SignContexts::new_omnilock( [secp256k1::SecretKey::from_slice(private_key.as_bytes())?].to_vec(), omni_cfg, ), )?; let json_tx = ckb_jsonrpc_types::TransactionView::from(tx_with_groups.get_tx_view().clone()); println!("tx: {}", serde_json::to_string_pretty(&json_tx).unwrap()); let tx_hash = CkbRpcClient::new(network_info.url.as_str()) .send_transaction(json_tx.inner, None) .expect("send transaction"); // example tx: 0xc0c9954a3299b540e63351146a301438372abf93682d96c7cce691c334dd5757 println!(">>> tx {} sent! <<<", tx_hash); Ok(()) } ``` -------------------------------- ### Importing CCC Object (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Imports the main `ccc` object from the installed CCC package. This object provides access to all the library's functionalities for wallet connection and interaction. ```TypeScript import { ccc } from "@ckb-ccc/"; ``` -------------------------------- ### Initial src/index.js Content - JavaScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Shows the default content of the main JavaScript file (`src/index.js`) within the CKB Duktape template. It illustrates how to import libraries like `molecule-javascript`, load a schema, identify a specific type (`Script`), and use the `CKB.debug` function as a placeholder for custom script logic. ```JavaScript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = schema.declarations[scriptTypeIndex] // Write your script logic here. CKB.debug(scriptType) ``` -------------------------------- ### Deploying CKB Scripts (Duktape, HTLC) using Node.js Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This Node.js script deploys the Duktape binary and a custom JavaScript script (like an HTLC script) onto a CKB dev chain. It reads the binaries from files, calculates required capacities, constructs a transaction with outputs for the scripts and change, signs it with a private key, and sends it to a CKB node, outputting the transaction hash. ```JavaScript #!/usr/bin/env node const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') if (process.argv.length !== 6) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const duktapeBinary = fs.readFileSync(process.argv[2]) const jsScript = fs.readFileSync(process.argv[3]) const privateKey = process.argv[4] const nodeUrl = process.argv[5] const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const duktapeBinaryCapacity = BigInt(duktapeBinary.length) * 100000000n + 4100000000n const jsScriptCapacity = BigInt(jsScript.length) * 100000000n + 4100000000n const outputs = [ { lock: { codeHash: '0x0000000000000000000000000000000000000000000000000000000000000000', hashType: 'data', args: '0x' }, type: null, capacity: '0x' + duktapeBinaryCapacity.toString(16) }, { lock: { codeHash: '0x0000000000000000000000000000000000000000000000000000000000000000', hashType: 'data', args: '0x' }, type: null, capacity: '0x' + jsScriptCapacity.toString(16) }, { lock: lockScript, type: null, capacity: '0x' + (totalCapacity - jsScriptCapacity - duktapeBinaryCapacity - fee).toString(16) } ] const outputsData = [ utils.bytesToHex(duktapeBinary), utils.bytesToHex(jsScript), '0x' ] const transaction = { version: '0x0', cellDeps: [ { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs, witnesses: [ { lock: '', inputType: '', outputType: '' } ], outputsData } const signedTransaction = ckb.signTransaction(privateKey)(transaction) const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('deploy_scripts_result.txt', txHash) } run() ``` -------------------------------- ### View OffCKB Available Commands Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Displays the main help message for the OffCKB CLI, listing all available commands, their descriptions, and global options. This is useful for discovering the tool's capabilities. ```bash offckb --help ``` -------------------------------- ### Generate Glossary Terms File (Yarn/Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/README.md Shows the bash command to regenerate the 'key-terms.json' file from the glossary markdown file ('docs/tech-explanation/glossary.md'). This file is used by the Tooltip component. This command should be run inside the 'website' folder. ```bash yarn gen-terms ``` -------------------------------- ### Example Nervos CKB Block Structure Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/tech-explanation/block.md This JSON object provides a sample representation of a Nervos CKB block, illustrating the structure and typical values for its main fields: header, transactions, uncles, and proposals. ```json { "uncles": [ { "proposals": [], "header": { "compact_target": "0x1a9c7b1a", "hash": "0x87764caf4a0e99302f1382421da1fe2f18382a49eac2d611220056b0854868e3", "number": "0x129d3", "parent_hash": "0x815ecf2140169b9d283332c7550ce8b6405a120d5c21a7aa99d8a75eb9e77ead", "nonce": "0x78b105de64fc38a200000004139b0200", "timestamp": "0x16e62df76ed", "transactions_root": "0x66ab0046436f97aefefe0549772bf36d96502d14ad736f7f4b1be8274420ca0f", "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "uncles_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "version": "0x0", "epoch": "0x7080291000049", "dao": "0x7088b3ee3e738900a9c257048aa129002cd43cd745100e000066ac8bd8850d00" } } ], "proposals": ["0x5b2c8121455362cf70ff"], "transactions": [ { "version": "0x0", "cell_deps": [], "header_deps": [], "inputs": [ { "previous_output": { "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "index": "0xffffffff" }, "since": "0x129d5" } ], "outputs": [ { "capacity": "0x1996822511", "lock": { "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "args": "0x2ec3a5fb4098b14f4887555fe58d966cab2c6a63", "hash_type": "type" }, "type": null } ], "outputs_data": ["0x"], "witnesses": [ "0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000002ec3a5fb4098b14f4887555fe58d966cab2c6a6300000000" ], "hash": "0x84395bf085f48de9f8813df8181e33d5a43ab9d92df5c0e77d711e1d47e4746d" } ], "header": { "compact_target": "0x1a9c7b1a", "hash": "0xf355b7bbb50627aa26839b9f4d65e83648b80c0a65354d78a782744ee7b0d12d", "number": "0x129d5", "parent_hash": "0x4dd7ae439977f1b01a8c9af7cd4be2d7bccce19fcc65b47559fe34b8f32917bf", "nonce": "0x91c4b4746ffb69fe000000809a170200", "timestamp": "0x16e62dfdb19", "transactions_root": "0x03c72b4c2138309eb46342d4ab7b882271ac4a9a12d2dcd7238095c2d131caa6", "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "uncles_hash": "0x90eb89b87b4af4c391f3f25d0d9f59b8ef946d9627b7e86283c68476fee7328b", "version": "0x0", "epoch": "0x7080293000049", "dao": "0xae6c356c8073890051f05bd38ea12900939dbc2754100e0000a0d962db850d00" } } ``` -------------------------------- ### Response: Show Project Structure - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx Output showing the directory tree of the workspace, including the `contracts/carrot` directory and its source file `main.rs`, along with test files. ```Bash . ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.md ├── contracts │ └── carrot │ ├── Cargo.toml │ ├── Makefile │ ├── README.md │ └── src │ └── main.rs ├── scripts │ └── find_clang └── tests ├── Cargo.toml └── src ├── lib.rs └── tests.rs 7 directories, 13 files ``` -------------------------------- ### Load Schemas and Deserialize Script Args (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Loads the generated Molecule schemas (`blockchain-combined.json` and `htlc-combined.json`) and uses `molecule-javascript` to deserialize the current CKB script and extract/deserialize its arguments (`HtlcArgs`). Includes helper functions for hex conversion. ```javascript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = new Molecule(schema.declarations[scriptTypeIndex]) // Write your script logic here. const customSchema = require('./htlc-combined.json') const customNames = customSchema.declarations.map(d => d.name) const htlcArgsIndex = customNames.indexOf('HtlcArgs') const htlcArgsType = new Molecule(customSchema.declarations[htlcArgsIndex]) function bytesToHex(b) { return "0x" + Array.prototype.map.call( new Uint8Array(b), function(x) { return ('00' + x.toString(16)).slice(-2) } ).join('') } function hexStringArrayToHexString(a) { let s = "0x"; for (let i = 0; i < a.length; i++) { s = s + a[i].substr(2) } return s } const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) CKB.debug(`a: ${hexStringArrayToHexString(htlcArgs[0][1])}`) CKB.debug(`b: ${hexStringArrayToHexString(htlcArgs[1][1])}`) CKB.debug(`c: ${hexStringArrayToHexString(htlcArgs[2][1])}`) ``` -------------------------------- ### Query Transaction State with Lumos SDK Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/how-tos/how-to-query-tx-state.mdx Example JavaScript code using the Lumos SDK to interact with the CKB RPC. It demonstrates how to use `rpc.sendTransaction` to broadcast a transaction and then `rpc.getTransaction` to query its state using the returned transaction hash. ```javascript const txHash = await rpc.sendTransaction(tx, "passthrough"); const state = await rpc.getTransaction(txHash); ``` -------------------------------- ### Constructing and Sending CKB Transaction (JS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This JavaScript snippet demonstrates how to add an input to a CKB transaction, prepare witnesses, sign the transaction using a private key, and then either perform a dry run for validation or send the transaction to the CKB node. It includes error handling for the dry run and logging the results. ```JavaScript transaction.inputs.push({ previousOutput: { txHash: htlcCellTxHash, index: "0x0" }, since: '0x0' }) transaction.witnesses[0] = { lock: '', inputType: '', outputType: '' } const signedTransaction = ckb.signTransaction(privateKey)(transaction) signedTransaction.witnesses.push(htlcWitness) if (dryrun) { try { const result = await ckb.rpc.dryRunTransaction(signedTransaction) console.log(`Dry run success result: ${JSON.stringify(result, null, 2)}`) } catch (e) { console.log(`Dry run failure result: ${JSON.stringify(JSON.parse(e.message), null, 2)}`) } } else { const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('unlock_via_timeout_result.txt', txHash) } } run() ``` -------------------------------- ### Initialize CKB Script Project with OFFCKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx Use the OFFCKB tool to create a new boilerplate project directory for CKB scripts. This command fetches a template from a specified or default repository. ```bash offckb create --script sudt-script ``` -------------------------------- ### OffCKB Deploy Callee Response Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Output showing the successful deployment of the 'callee' contract, including the transaction hash, confirmation status, and generated deployment files. ```sh contract callee deployed, tx hash: 0xdb91398beafb3c41b3e6f4c4a078a08aa1f4245b0d964b9d51913e8514f20b72 wait for tx confirmed on-chain... tx committed. callee deployment.toml file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/callee/deployment.toml generated successfully. callee migration json file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/callee/migrations/2024-11-23-133257.json generated successfully. done. ``` -------------------------------- ### Initialize CKB DAO Deposit Transaction Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Starts the process of creating a transaction object for depositing CKB into the Nervos DAO, setting up the output with the user's lock script and the DAO type script. ```TypeScript onClick={async () => { if (!signer) { return; } const { script: lock } = await signer.getRecommendedAddressObj(); const tx = ccc.Transaction.from({ outputs: [ { lock, type: await ccc.Script.fromKnownScript( signer.client, ccc.KnownScript.NervosDao, "0x" ), }, ], ``` -------------------------------- ### Query Transaction State with JSON-RPC Request Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/how-tos/how-to-query-tx-state.mdx Example JSON-RPC request payload for the `get_transaction` method. It requires the transaction hash as a parameter to retrieve the transaction details and its current status on the network. ```json { "id": 42, "jsonrpc": "2.0", "method": "get_transaction", "params": [ "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3" ] } ``` -------------------------------- ### Serialize Empty Uint32Vec Fixvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Demonstrates the serialization of an empty fixed vector of Uint32 (vector Uint32Vec ;). The serialized form is the 4-byte length prefix, which is 0. ```Hex Bytes 00 00 00 00 ``` -------------------------------- ### Display CKB-CLI Help Documentation Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ckb-cli.mdx Commands to display the top-level help documentation for ckb-cli and specific help for sub-commands like `rpc`. ```Shell # Top level help doc ckb-cli --help # RPC help doc ckb-cli rpc --help ``` -------------------------------- ### Deserialize HtlcArgs from Script Arguments (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Specifically shows how to use the `HtlcArgs` Molecule type, previously loaded from the schema, to deserialize the extracted script arguments string into the structured `htlcArgs` object. ```javascript const htlcArgs = htlcArgsType.deserialize(args) ``` -------------------------------- ### Deploying Duktape and HTLC Script on CKB (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This script deploys the Duktape VM binary and the HTLC JavaScript script onto the CKB blockchain as separate cells. It reads the binary and script files, calculates the required capacity for each, constructs a transaction with outputs containing the script data, signs the transaction using a provided private key, and sends it to a specified CKB node URL. The transaction hash is printed and saved to a file. ```JavaScript #!/usr/bin/env node const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') if (process.argv.length !== 6) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const duktapeBinary = fs.readFileSync(process.argv[2]) const jsScript = fs.readFileSync(process.argv[3]) const privateKey = process.argv[4] const nodeUrl = process.argv[5] const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const duktapeBinaryCapacity = BigInt(duktapeBinary.length) * 100000000n + 4100000000n const jsScriptCapacity = BigInt(jsScript.length) * 100000000n + 4100000000n const outputs = [ { lock: { codeHash: '0x0000000000000000000000000000000000000000000000000000000000000000', hashType: 'data', args: '0x' }, type: null, capacity: '0x' + duktapeBinaryCapacity.toString(16) }, { lock: { codeHash: '0x0000000000000000000000000000000000000000000000000000000000000000', hashType: 'data', args: '0x' }, type: null, capacity: '0x' + jsScriptCapacity.toString(16) }, { lock: lockScript, type: null, capacity: '0x' + (totalCapacity - jsScriptCapacity - duktapeBinaryCapacity - fee).toString(16) } ] const outputsData = [ utils.bytesToHex(duktapeBinary), utils.bytesToHex(jsScript), '0x' ] const transaction = { version: '0x0', cellDeps: [ { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs, witnesses: [ { lock: '', inputType: '', outputType: '' } ], outputsData } const signedTransaction = ckb.signTransaction(privateKey)(transaction) const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('deploy_scripts_result.txt', txHash) } run() ``` -------------------------------- ### Check Account Balance in OffCKB REPL Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Demonstrates how to initialize a client and check the balance of a specific account using the OffCKB REPL. ```console OffCKB > let myClient = Client.fromUrl(networks.testnet.rpc_url, 'testnet'); OffCKB > await myClient.getBalanceSingle(accounts[0].lockScript); 60838485293944n OffCKB > ``` -------------------------------- ### Building and Testing CKB Transaction with Custom Script (Lumos JS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Shows how to build a transaction skeleton, perform a transfer, modify an output cell to include a custom type script (`carrotTypeScript`) and data, add a cell dependency for the script code, pay fees, prepare signing entries, sign the transaction, and send it. This example specifically tests a script that rejects transactions with "carrot" in cell data, resulting in a transaction verification error. Requires `indexer`, `wallet`, `wallet2`, `carrotTypeScript`, and `carrotTxHash`. ```JavaScript > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"400" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.cellOutput.type = carrotTypeScript; cell.data = "0x" + Buffer.from("carrot123", "utf8").toString("hex"); return outputs; }); > txSkeleton = lumos.helpers.addCellDep(txSkeleton, { outPoint: { txHash: carrotTxHash, index: "0x0", }, depType: "code", }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures); > await rpc.sendTransaction(signedTx); ``` -------------------------------- ### Debugging CKB Script with ckb-debugger and GDB (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Shows the sequence of commands to start `ckb-debugger` in GDB server mode listening on a specific address/port, and then connect a `riscv64-unknown-elf-gdb` client to that server for interactive debugging of a compiled RISC-V script binary. ```Bash ckb-debugger --mode gdb --gdb-listen 127.0.0.1:9999 --bin fib riscv64-unknown-elf-gdb fib (gdb) target remote 127.0.0.1:9999 (gdb) b fib (gdb) c ``` -------------------------------- ### List OffCKB System Scripts for Devnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Demonstrates how to list information about the built-in system scripts available on the devnet using the OffCKB CLI. ```bash offckb system-scripts --network devnet ``` -------------------------------- ### Compile Duktape for CKB using Docker Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Provides the necessary bash commands to clone the ckb-duktape repository, initialize submodules, and compile the project into a RISC-V executable binary using a pre-configured Docker environment with the CKB RISC-V toolchain. ```Bash $ git clone https://github.com/xxuejie/ckb-duktape.git $ cd ckb-duktape $ git submodule init $ git submodule update $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash root@0d31cad7a539:~# cd /code root@0d31cad7a539:/code# make riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/entry.c -c -o build/entry.o riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror duktape/duktape.c -c -o build/duktape.o riscv64-unknown-elf-gcc build/entry.o build/duktape.o -o build/duktape -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/repl.c -c -o build/repl.o riscv64-unknown-elf-gcc build/repl.o build/duktape.o -o build/repl -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/dump_load.c -c -o build/dump_load.o riscv64-unknown-elf-gcc build/dump_load.o build/duktape.o -o build/dump_load -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s gcc -Wall -Werror -Iduktape -O3 c/native_dump_bytecode.c duktape/duktape.c -o build/native_dump_bytecode -lm riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/dump_load_nocleanup.c -c -o build/dump_load_nocleanup.o riscv64-unknown-elf-gcc build/dump_load_nocleanup.o build/duktape.o -o build/dump_load_nocleanup -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s gcc -Wall -Werror -Ischema -Ideps/ckb-c-stdlib/molecule -O3 c/native_args_assembler.c -o build/native_args_assembler root@0d31cad7a539:/code# exit exit $ ls build/ duktape dump_load dump_load_nocleanup entry.o native_dump_bytecode repl.o duktape.o dump_load.o dump_load_nocleanup.o native_args_assembler repl ``` -------------------------------- ### ZetZ Carrot Example Contract Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-10.md This ZetZ code snippet demonstrates a simple smart contract that loads cell data and checks if it contains the string 'carrot'. It utilizes the 'where' clause to enforce static checks on function arguments, ensuring buffer size requirements are met at build time. ```ZetZ using as ckb using ::{memcmp}; fn load_data(u64 index, u8 mut * buffer) -> int where len(buffer) >= 6 { u64 mut l = 6; int ret = asckb::ckb_load_cell_data(buffer, &l, 0, index, 2); return ret; } export fn main () -> int { u64 index = 0; while true { u8 buffer[6]; int ret = load_data(index, buffer); if ret == 1 { break; } if memcmp(buffer, "carrot", 6) == 0 { return -1; } index++; } return 0; } ``` -------------------------------- ### Run CKB Contract Unit Tests using Make Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Executes the `make test` command to run the unit tests for the CKB contracts. ```Shell make test ``` -------------------------------- ### Serialize Empty Bytes Fixvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Demonstrates the serialization of an empty fixed vector of bytes (vector Bytes ;). The serialized form is just the 4-byte length prefix, which is 0 for an empty vector. ```Hex Bytes 00 00 00 00 ``` -------------------------------- ### Assembling UDT Script Arguments using Native Tool Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-3.md Bash commands demonstrating how to use a native tool (`native_args_assembler`) within a Docker container to combine the UDT JavaScript source file (`udt.js`) and the transaction `outPointHex` into the final arguments required by the CKB script. ```bash cd ckb-duktape docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash root@0d31cad7a539:~# cd /code root@0d31cad7a539:/code# ./build/native_args_assembler -f udt.js -t 6a5f904a6f6ec270b6dde3add221aa8a82120e2e98ea6dac59160dd09359084201000000 ``` -------------------------------- ### Connecting GDB to Remote CKB Debugger (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md Starts a Docker container with the CKB RISC-V toolchain, mounts the current directory, changes into it, and then launches `riscv64-unknown-elf-gdb` to connect to the remote debugger instance running on a specific IP address and port (e.g., 192.168.1.230:2000). ```bash $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191012 bash root@66e3b39e0dfd:/# cd /code root@66e3b39e0dfd:/code# riscv64-unknown-elf-gdb carrot GNU gdb (GDB) 8.3.0.20190516-git Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from carrot... (gdb) target remote 192.168.1.230:2000 Remote debugging using 192.168.1.230:2000 0x00000000000100c6 in _start () (gdb) ``` -------------------------------- ### Build CKB VM Test Suite and Run RISC-V Binary Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-4.md Commands to clone the CKB VM test suite and CKB VM repositories, build the `binary` tool within the test suite using Cargo, and then use it to execute the compiled `fib_riscv64` RISC-V program with different inputs (5 and 10) on a simulated CKB VM. ```Shell $ git clone --recursive https://github.com/nervosnetwork/ckb-vm-test-suite $ cd ckb-vm-test-suite $ git clone https://github.com/nervosnetwork/ckb-vm $ cd binary $ cargo build --release $ cd ../.. $ ckb-vm-test-suite/binary/target/release/asm64 fib_riscv64 5 $ ckb-vm-test-suite/binary/target/release/asm64 fib_riscv64 10 ``` -------------------------------- ### Loading Cell Data with CKB Syscalls C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This CKB script demonstrates how to use syscalls, specifically `ckb_load_cell_data`, to read data from output cells. It iterates through output cells, loading the first 6 bytes of data into a buffer. If any cell's data starts with the string "carrot", the script returns -1, indicating failure; otherwise, it returns 0 upon checking all output cells. ```C #include #include "ckb_syscalls.h" int main(int argc, char* argv[]) { int ret; size_t index = 0; uint64_t len = 0; /* (1) */ unsigned char buffer[6]; while (1) { len = 6; memset(buffer, 0, 6); ret = ckb_load_cell_data(buffer, &len, 0, index, CKB_SOURCE_OUTPUT); /* (2) */ if (ret == CKB_INDEX_OUT_OF_BOUND) { /* (3) */ break; } if (memcmp(buffer, "carrot", 6) == 0) { return -1; } index++; } return 0; } ``` -------------------------------- ### VSCode Tasks for Starting and Stopping ckb-debugger (JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Configures VSCode `tasks.json` with two tasks: `StartDbg-Rust` which runs `ckb-debugger` in GDB mode for a specified script binary and listening address, and `StopCkbDebugger` which attempts to kill the `ckb-debugger` process. ```JSON { "label": "StartDbg-Rust", "isBackground": true, "type": "process", "command": "ckb-debugger", "args": [ "--bin=rust/build/release/ckb-c1.debug", "--mode=gdb", "--gdb-listen=127.0.0.1:8000" ], "options": { "cwd": "${workspaceRoot}" } }, { "label": "StopCkbDebugger", "type": "shell", "command": "killall ckb-debugger || true" } ``` -------------------------------- ### Defining Attributes Struct Molecule C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/example-role-playing-game.mdx Defines the `Attributes` structure, which represents the core character attributes (strength, dexterity, etc.) for a role. It is a fixed-size structure containing 8 fields, each of type `AttrValue`, imported from `common/basic_types`. ```c import common/basic_types; // Each role has 8 attributes. The size is fixed. struct Attributes { strength: AttrValue, dexterity: AttrValue, endurance: AttrValue, speed: AttrValue, intelligence: AttrValue, wisdom: AttrValue, perception: AttrValue, concentration: AttrValue, } ``` -------------------------------- ### Run CKB Debugger with Generated Transaction (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This command navigates to the `htlc-runner` directory, makes the runner script executable, sets the debug log level for Rust components, and executes the runner script. The runner script uses the previously generated `tx.json` and the specified duktape and JS script binaries to run the transaction through the CKB debugger. ```Shell $ cd $TOP/htlc-runner $ chmod +x runner.js $ RUST_LOG=debug `./runner.js ../ckb-duktape/build/load0 ../htlc-template/build/duktape.js` ``` -------------------------------- ### CKB Debugger Transaction Skeleton (JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md A JSON structure representing a mock transaction and its dependencies (inputs, cell deps, header deps) used as a template for debugging CKB scripts. It includes placeholders like @DUKTAPE_HASH, @SCRIPT_CODE, and @DUKTAPE_CODE. ```json { "mock_info": { "inputs": [ { "input": { "previous_output": { "tx_hash": "0xa98c57135830e1b91345948df6c4b8870828199a786b26f09f7dec4bc27a73da", "index": "0x0" }, "since": "0x0" }, "output": { "capacity": "0x4b9f96b00", "lock": { "args": "0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8", "code_hash": "@DUKTAPE_HASH", "hash_type": "data" }, "type": null }, "data": "0x" } ], "cell_deps": [ { "cell_dep": { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x0" }, "dep_type": "code" }, "output": { "capacity": "0x702198d000", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null }, "data": "@SCRIPT_CODE" }, { "cell_dep": { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x1" }, "dep_type": "code" }, "output": { "capacity": "0x702198d000", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null }, "data": "@DUKTAPE_CODE" } ], "header_deps": [ { "compact_target": "0x1a1e4c2f", "hash": "0x51d199c4060f703344eab3c9b8794e6c60195ae9093986c35dba7c3486224409", "number": "0xd8fc4", "parent_hash": "0xc02e01eb57b205c6618c9870667ed90e13adb7e9a7ae00e7a780067a6bfa6a7b", "nonce": "0xca8c7caa8100003400231b4f9d6e0300", "timestamp": "0x17061eab69e", "transactions_root": "0xffb0863f4ae1f3026ba99b2458de2fa69881f7508599e2ff1ee51a54c88b5f88", "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "uncles_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "version": "0x0", "epoch": "0x53f00fa000232", "dao": "0x4bfe53a5a9bb9a30c88898b9dfe22300a58f2bafed47680000d3b9f5b6630107" } ] }, "tx": { "version": "0x0", "cell_deps": [ { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x0" }, "dep_type": "code" }, { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x1" }, "dep_type": "code" } ], "header_deps": [ "0x51d199c4060f703344eab3c9b8794e6c60195ae9093986c35dba7c3486224409" ], "inputs": [ { "previous_output": { "tx_hash": "0xa98c57135830e1b91345948df6c4b8870828199a786b26f09f7dec4bc27a73da", "index": "0x0" }, "since": "0x0" } ], "outputs": [ { "capacity": "0x0", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null } ], "witnesses": [ "0x210000000c0000001d0000000d0000006920616d20612073656372657400000000" ], "outputs_data": [ "0x" ] } } ``` -------------------------------- ### BTC Unlocking Script Example (3 and 5) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/ckb-vs-btc.mdx A simple Bitcoin unlocking script (`scriptSig`) that provides the numbers 3 and 5. When executed with the corresponding locking script (`OP_ADD <8> OP_EQUAL`), these numbers sum to 8, satisfying the locking condition. ```Bitcoin Script OP_3 OP_5 ``` -------------------------------- ### Generating CKB Address from Private Key (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Provides a Rust example for generating a new CKB address. It shows how to generate a random private key, derive the public key using secp256k1, create an address payload, and construct the final CKB address for a specified network type. ```Rust use ckb_sdk::types::{Address, AddressPayload, NetworkType}; use rand::Rng; let mut rng = rand::thread_rng(); let privkey_bytes: [u8; 32] = rng.gen(); let secp_secret_key = secp256k1::SecretKey::from_slice(&privkey_bytes).unwrap(); let pubkey = secp256k1::PublicKey::from_secret_key(&ckb_crypto::secp::SECP256K1, &secp_secret_key); let payload = AddressPayload::from_pubkey(&pubkey); let address = Address::new(NetworkType::Mainnet, payload, true); println!("address: {}", address.to_string()); ``` -------------------------------- ### Deploying ckb-duktape REPL Binary on CKB - Node.js Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This Node.js snippet demonstrates how to use the @ckb-lumos/lumos library to create and send a transaction that deploys the compiled `build/repl` binary onto the CKB testnet. It initializes Lumos config, sets up RPC and Indexer, defines wallets, reads the binary file, creates a transaction skeleton, transfers funds, adds the binary data to an output cell, pays the fee, prepares signing entries, signs the transaction, and sends it. ```javascript $ node Welcome to Node.js v20.12.0. Type ".help" for more information. > > > const lumos = require("@ckb-lumos/lumos"); > const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); > const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); > lumos.config.initializeConfig(lumos.config.TESTNET); > const wallet = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqvwg2cen8extgq8s5puft8vf40px3f599cytcyd8", privkey: "0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6", }; > const wallet2 = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2prryvze6fhufxkgjx35psh7w70k3hz7c3mtl4d", privkey: "0xace08599f3174f4376ae51fdc30950d4f2d731440382bb0aa1b6b0bd3a9728cd" } > const data = fs.readFileSync("./ckb-duktape/build/repl"); > data.byteLength 306040 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"306240" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const duktapeReplTxHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### Serialize Single Byte in Bytes Fixvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Shows the serialization of a fixed vector containing a single byte (0x12). The serialized form includes the 4-byte length prefix (1) followed by the serialized item. ```Hex Bytes 01 00 00 00, 12 ``` -------------------------------- ### Serialize Multiple Bytes in Bytes Fixvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Illustrates the serialization of a fixed vector containing multiple bytes (0x1234567890abcdef). The serialized form includes the 4-byte length prefix (8) followed by the serialized items. ```Hex Bytes 08 00 00 00, 12 34 56 78 90 ab cd ef ``` -------------------------------- ### Get CKB Light Client Tip Header (Curl Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Curl command executed in bash to send a JSON-RPC request to the running CKB light client's default RPC port (9000) to retrieve the current block header at the tip of the synchronized chain. ```bash curl http://localhost:9000/ -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "get_tip_header", "params": [], "id": 1}' ``` -------------------------------- ### Running CKB Standalone Debugger in GDB Mode (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md Installs the `ckb-standalone-debugger` via `cargo` and then runs it in GDB mode, listening on port 2000. It uses the `carrot.json` file, targeting the output cell at index 0, and debugging the type script group. ```bash $ cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger $ ckb-debugger --mode gdb --gdb-listen 0.0.0.0:2000 --tx-file carrot.json --cell-index 0 --cell-type output --script-group-type type ``` -------------------------------- ### Get Filtered Scripts from CKB Light Client (Curl Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Curl command to send a JSON-RPC request to the light client to retrieve the list of scripts that have been previously configured for filtering using the `set_scripts` method. ```bash curl http://localhost:9000/ -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method":"get_scripts", "params": [], "id": 1}' ``` -------------------------------- ### Serialize Multiple Bytes in BytesVec Dynvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Illustrates the serialization of a dynamic vector containing multiple Bytes items. The serialized form includes the total size prefix, offsets for each item, and the serialized items concatenated. ```Hex Bytes 34 00 00 00\n18 00 00 00, 1e 00 00 00, 22 00 00 00, 28 00 00 00, 2d 00 00 00\n02 00 00 00, 12 34\n00 00 00 00,\n02 00 00 00, 05 67\n01 00 00 00, 89\n03 00 00 00, ab cd ef ``` -------------------------------- ### CKB Transaction Structure JSON Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/ckb-vs-btc.mdx Defines the data structure of a CKB transaction, including version, cell dependencies, header dependencies, inputs, witnesses, outputs, and output data. It shows the various fields and their types or example values. ```JSON { "version": 0, // Transaction version number "cell_deps": [ // An array of outpoint pointing to the Cells that are dependencies of this transaction. { "out_point": { // A cell outpoint that point to the Cells used as deps. "tx_hash": "0xbd864a269201d7052d4eb3f753f49f7c68b8edc386afc8bb6ef3e15a05facca2", "index": "0x0" }, "dep_type": "dep_group" // Dependency type (0 for Code, 1 for DepGroup) } ], "header_deps": [ // An array of hashes pointing to block headers that are dependencies of this transaction. "0xaa1124da6a230435298d83a12dd6c13f7d58caf7853f39cea8aad992ef88a422" ], "inputs": [ // An array of referenced Cell inputs. { "previous_output": { "tx_hash": "0x8389eba3ae414fb6a3019aa47583e9be36d096c55ab2e00ec49bdb012c24844d", "index": "0x1" }, "since": "0x0" // Timelock feature } ], "witnesses": [ // Provided by transaction creator to make the execution of corresponding Lock Script success. "0x55000000100000005500000055000000410000004a975e08ff99fa0001 42ff3b86a836b43884b5b46f91b149f7cc5300e8607e633b7a29c94dc01c6616a12f62e74a1 415f57fcc5a00e41ac2d7034e90edf4fdf800" ], "outputs": [ // An array of Cells that are used as outputs, { "capacity": "0x746a528800", "lock": { "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "args": "0x56008385085341a6ed68decfabb3ba1f3eea7b68", "hash_type": "type" }, "type": null }, { "capacity": "0x1561d9307e88", "lock": { "code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "args": "0x886d23a7858f12ebf924baaacd774a5e2cf81132", "hash_type": "type" }, "type": null } ], "outputs_data": [ // An array of Cell data for each Cell output. "0x", "0x" ] } ``` -------------------------------- ### Set Scripts for CKB Light Client Filtering (Curl Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Curl command to send a JSON-RPC request to the light client to configure which scripts it should monitor. The example demonstrates setting a lock script filter using a specific code hash and arguments. ```bash curl http://localhost:9000/ -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method":"set_scripts", "params": [[{"script": {"code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "hash_type": "type", "args": "0x64257f00b6b63e987609fa9be2d0c86d351020fb"}, "script_type": "lock", "block_number": "0x0"}]], "id": 1}' ``` -------------------------------- ### Setting up Docker Environment for GDB (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md Runs a Docker container with the necessary RISC-V GNU toolchain, mounting the current directory, and changes the directory inside the container to the mounted code location to prepare for the GDB session. ```Bash sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191012 bash cd /code ``` -------------------------------- ### Query Transaction State with JSON-RPC Response Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/how-tos/how-to-query-tx-state.mdx Example JSON-RPC response payload returned by the `get_transaction` method. It includes the full transaction object, execution cycles, time added to the pool, fee, minimum replace fee, and the transaction's current status. ```json { "id": 42, "jsonrpc": "2.0", "result": { "transaction": { "cell_deps": [ { "dep_type": "code", "out_point": { "index": "0x0", "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3" } } ], "hash": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3", "header_deps": [ "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed" ], "inputs": [ { "previous_output": { "index": "0x0", "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17" }, "since": "0x0" } ], "outputs": [ { "capacity": "0x2540be400", "lock": { "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5", "hash_type": "data", "args": "0x" }, "type": null } ], "outputs_data": [ "0x" ], "version": "0x0", "witnesses": [] }, "cycles": "0x219", "time_added_to_pool" : "0x187b3d137a1", "fee": "0x16923f7dcf", "min_replace_fee": "0x16923f7f6a", "tx_status": { "block_hash": null, "block_number": null, "status": "pending", "reason": null } } } ``` -------------------------------- ### Generating New CKB Script 'callee' with make (Response) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx This output confirms the successful generation of the `callee` script module. It details the steps taken to create the necessary files and directories for the `callee` script within the `contracts` folder. ```bash 🤷 Project Name: callee 🔧 Destination: /tmp/spawn-script/contracts/callee ... 🔧 project-name: callee ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/spawn-script/contracts/callee`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/spawn-script/contracts/callee ``` -------------------------------- ### Create DOB Cluster with @ckb-ccc/ccc (TSX) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Demonstrates creating a DOB Cluster on Nervos using `@ckb-ccc/ccc`. It includes defining the DOB0 pattern for the cluster description, calling `createSporeCluster`, handling transaction fee completion, sending the transaction, and waiting for confirmation. Requires `@ckb-ccc/ccc` and a signer/client setup. ```tsx import { ccc } from "@ckb-ccc/ccc"; import { client, signer } from "@ckb-ccc/playground"; function getExplorerTxUrl(txHash: string) { const isMainnet = client.addressPrefix === "ckb"; const baseUrl = isMainnet ? "https://explorer.nervos.org" : "https://testnet.explorer.nervos.org"; return `${baseUrl}/transaction/${txHash}`; } /** * Generate cluster description */ function generateClusterDescriptionUnderDobProtocol() { const clusterDescription = "A simple loot cluster"; const dob0Pattern: ccc.spore.dob.PatternElementDob0[] = [ { traitName: "BackgroundColor", dobType: "String", dnaOffset: 0, dnaLength: 1, patternType: "options", traitArgs: ["red", "blue", "green", "black", "white"], }, { traitName: "Type", dobType: "Number", dnaOffset: 1, dnaLength: 1, patternType: "range", traitArgs: [10, 50], }, { traitName: "Timestamp", dobType: "Number", dnaOffset: 2, dnaLength: 4, patternType: "rawNumber", }, ]; const dob0: ccc.spore.dob.Dob0 = { description: clusterDescription, dob: { ver: 0, decoder: ccc.spore.dob.getDecoder(client, "dob0"), pattern: dob0Pattern, }, }; return ccc.spore.dob.encodeClusterDescriptionForDob0(dob0); } /** * create cluster */ const { tx: clusterTx, id: clusterId } = await ccc.spore.createSporeCluster({ signer, data: { name: "Simple loot", description: generateClusterDescriptionUnderDobProtocol(), }, }); await clusterTx.completeFeeBy(signer, 2000n); const clusterTxHash = await signer.sendTransaction(clusterTx); console.log( "Create cluster tx sent:", clusterTxHash, `Cluster ID: ${clusterId}` ); await signer.client.waitTransaction(clusterTxHash); console.log( "Create cluster tx committed:", getExplorerTxUrl(clusterTxHash), `Cluster ID: ${clusterId}` ); ``` -------------------------------- ### Execute CKB Script with Debugger from Dump Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md This command re-executes the script using the `runner.rb` helper, but this time the `ckb-debugger` uses the previously generated `dump0.bin` trace as input. The output shows the reduced cycle consumption achieved by skipping cleanup. ```Shell $ RUST_LOG=debug ./runner.rb dump0.bin script.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input DEBUG:: script group: Byte32(0x0e948e69dd75f2d6676048569073afe4ec2b284144bbe33a6216b13171606d18) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 3903352 Transfer cycles: 96994, running cycles: 3806358 ``` -------------------------------- ### Serializing HTLC Arguments with Molecule (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This snippet illustrates the process of serializing HTLC arguments into a Molecule binary format. It uses a helper function `hexStringToHexStringArray` to format input data and then utilizes the `molecule-javascript` library with a custom schema to serialize the arguments `a`, `b`, and `hash` into a byte array. ```JavaScript // ... function hexStringToHexStringArray(s) { let arr = [] for (let i = 2; i < s.length; i += 2) { arr.push('0x' + s.substr(i, 2)) } return arr } // ... const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcArgsType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcArgs")) const htlcScriptArgs = htlcArgsType.serialize([ ['a', hexStringToHexStringArray(lockHashA)], ['b', hexStringToHexStringArray(lockHashB)], ['hash', hexStringToHexStringArray('0x' + crc32('i am a secret'))] ]) // ... ``` -------------------------------- ### Deserializing HtlcArgs from Script Arguments (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Takes the extracted script arguments (assumed to be a hex string representation of the serialized HtlcArgs structure) and deserializes them into a usable JavaScript object using the HtlcArgs Molecule type. ```javascript const htlcArgs = htlcArgsType.deserialize(args) ``` -------------------------------- ### CKB Debugger Transaction Skeleton (JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Defines a skeleton JSON structure for a CKB transaction, intended for use with the CKB debugger. It includes mock information for inputs, cell dependencies, header dependencies, and the transaction structure itself, using placeholders like @DUKTAPE_HASH and @SCRIPT_CODE. ```json { "mock_info": { "inputs": [ { "input": { "previous_output": { "tx_hash": "0xa98c57135830e1b91345948df6c4b8870828199a786b26f09f7dec4bc27a73da", "index": "0x0" }, "since": "0x0" }, "output": { "capacity": "0x4b9f96b00", "lock": { "args": "0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8", "code_hash": "@DUKTAPE_HASH", "hash_type": "data" }, "type": null }, "data": "0x" } ], "cell_deps": [ { "cell_dep": { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x0" }, "dep_type": "code" }, "output": { "capacity": "0x702198d000", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null }, "data": "@SCRIPT_CODE" }, { "cell_dep": { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x1" }, "dep_type": "code" }, "output": { "capacity": "0x702198d000", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null }, "data": "@DUKTAPE_CODE" } ], "header_deps": [ { "compact_target": "0x1a1e4c2f", "hash": "0x51d199c4060f703344eab3c9b8794e6c60195ae9093986c35dba7c3486224409", "number": "0xd8fc4", "parent_hash": "0xc02e01eb57b205c6618c9870667ed90e13adb7e9a7ae00e7a780067a6bfa6a7b", "nonce": "0xca8c7caa8100003400231b4f9d6e0300", "timestamp": "0x17061eab69e", "transactions_root": "0xffb0863f4ae1f3026ba99b2458de2fa69881f7508599e2ff1ee51a54c88b5f88", "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "uncles_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "version": "0x0", "epoch": "0x53f00fa000232", "dao": "0x4bfe53a5a9bb9a30c88898b9dfe22300a58f2bafed47680000d3b9f5b6630107" } ] }, "tx": { "version": "0x0", "cell_deps": [ { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x0" }, "dep_type": "code" }, { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x1" }, "dep_type": "code" } ], "header_deps": [ "0x51d199c4060f703344eab3c9b8794e6c60195ae9093986c35dba7c3486224409" ], "inputs": [ { "previous_output": { "tx_hash": "0xa98c57135830e1b91345948df6c4b8870828199a786b26f09f7dec4bc27a73da", "index": "0x0" }, "since": "0x0" } ], "outputs": [ { "capacity": "0x0", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null } ], "witnesses": [ "0x210000000c0000001d0000000d0000006920616d20612073656372657400000000" ], "outputs_data": [ "0x" ] } } ``` -------------------------------- ### Serialize Empty BytesVec Dynvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Demonstrates the serialization of an empty dynamic vector of Bytes (vector BytesVec ;). The serialized form is the 4-byte total size prefix, which is 4 for an empty dynvec (size of the size prefix itself). ```Hex Bytes 04 00 00 00 ``` -------------------------------- ### Serialize Single Bytes in BytesVec Dynvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Shows the serialization of a dynamic vector containing a single Bytes item ([0x1234]). The serialized form includes the total size prefix, the offset to the first item, and the serialized item itself. ```Hex Bytes 0e 00 00 00\n08 00 00 00\n02 00 00 00 12 34 ``` -------------------------------- ### OffCKB Deploy Caller Response Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Output showing the successful deployment of the 'caller' contract, including the transaction hash, confirmation status, and generated deployment files. ```sh contract caller deployed, tx hash: 0x74bed00091f062e46225662fc90e460a4cc975478117eaa8570d454bf8dc58e9 wait for tx confirmed on-chain... tx committed. caller deployment.toml file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/caller/deployment.toml generated successfully. caller migration json file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/caller/migrations/2024-11-23-133222.json generated successfully. done. ``` -------------------------------- ### Example CKB Transaction and Mock Info (JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md This JSON snippet defines the structure for a CKB transaction (`tx`) and associated mock information (`mock_info`) used for debugging. It includes details about inputs, cell dependencies, header dependencies, outputs, witnesses, and output data, referencing external data like `@FIB_HASH`, `@FIB_CODE`, and `@FIB_ARG`. ```JSON { "mock_info": { "inputs": [ { "input": { "previous_output": { "tx_hash": "0xa98c57135830e1b91345948df6c4b8870828199a786b26f09f7dec4bc27a73da", "index": "0x0" }, "since": "0x0" }, "output": { "capacity": "0x4b9f96b00", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": { "args": "0x", "code_hash": "@FIB_HASH", "hash_type": "data" } }, "data": "0x" } ], "cell_deps": [ { "cell_dep": { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x0" }, "dep_type": "code" }, "output": { "capacity": "0x702198d000", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null }, "data": "@FIB_CODE" } ], "header_deps": [] }, "tx": { "version": "0x0", "cell_deps": [ { "out_point": { "tx_hash": "0xfcd1b3ddcca92b1e49783769e9bf606112b3f8cf36b96cac05bf44edcf5377e6", "index": "0x0" }, "dep_type": "code" } ], "header_deps": [ ], "inputs": [ { "previous_output": { "tx_hash": "0xa98c57135830e1b91345948df6c4b8870828199a786b26f09f7dec4bc27a73da", "index": "0x0" }, "since": "0x0" } ], "outputs": [ { "capacity": "0x0", "lock": { "args": "0x", "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash_type": "data" }, "type": null } ], "witnesses": [ "@FIB_ARG" ], "outputs_data": [ "0x" ] } } ``` -------------------------------- ### Serialize Multiple Uint32s in Uint32Vec Fixvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Illustrates the serialization of a fixed vector containing multiple Uint32 values. The serialized form includes the 4-byte length prefix (6) followed by the serialized items (each Uint32 in little-endian). ```Hex Bytes 06 00 00 00\n23 01 00 00, 56 04 00 00, 90 78 00 00, 0a 00 00 00, bc 00 00 00, ef 0d 00 00 ``` -------------------------------- ### Get Tip Header via RPC (Bash/JSON) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-public-rpc-node.mdx Demonstrates how to call the get_tip_header RPC method using curl to query the latest block information from the CKB node via the Nginx proxy. Shows the expected JSON result structure. Requires curl and the Nginx proxy to be running. ```bash echo '{ "id": 2, "jsonrpc": "2.0", "method": "get_tip_header", "params": [] }' \ | tr -d '\n' \ | curl -H 'content-type: application/json' -d @- \ http://192.168.1.100:80 ``` ```json { "jsonrpc": "2.0", "result": { "compact_target": "0x1d090fbe", "dao": "0xba17553fab3db84154bc4aa9f09b2600e826a2b0df99010400ed51b4686b5808", "epoch": "0x7080687001539", "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "hash": "0x7a46e779a3fc2d5b55c82aad852e721b0097bf873927b9751409b1d185599ce4", "nonce": "0xd265e70dfd205dbbed33b29294121856", "number": "0x7037f2", "parent_hash": "0x3d105fe9ec60f138baa6623abd16af70ba1be90ad23d1943bcaa55d5f14fcb6f", "proposals_hash": "0x2581d1769886226a8c90ee99baf2d8696e24c7f6bb6751748ff8b4452f8006e5", "timestamp": "0x1847a2bfad2", "transactions_root": "0x28157a5962c4ae1d3e153b1d8d331e5fd3c158866287f5398ab7f7d38210dfb0", "version": "0x0" }, "id": 2 } ``` -------------------------------- ### Helper Function to Convert Hex String to Array (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This helper function takes a hexadecimal string (prefixed with '0x') as input and converts it into an array of byte strings, where each byte is represented as a '0x' prefixed hex string. It's typically used to prepare byte data for serialization with libraries like Molecule. ```JavaScript function hexStringToHexStringArray(s) { let arr = [] for (let i = 2; i < s.length; i += 2) { arr.push('0x' + s.substr(i, 2)) } return arr } ``` -------------------------------- ### Create Spore with @ckb-ccc/ccc (TSX) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx Shows how to mint a Spore linked to a DOB Cluster using `@ckb-ccc/ccc`. It includes generating simple DNA content, calling `createSpore` with the cluster ID, handling transaction fee completion, sending the transaction, and waiting for confirmation. Requires `@ckb-ccc/ccc`, a signer/client setup, and a valid cluster ID. ```tsx import { ccc } from "@ckb-ccc/ccc"; import { client, signer } from "@ckb-ccc/playground"; function getExplorerTxUrl(txHash: string) { const isMainnet = client.addressPrefix === "ckb"; const baseUrl = isMainnet ? "https://explorer.nervos.org" : "https://testnet.explorer.nervos.org"; return `${baseUrl}/transaction/${txHash}`; } function generateSimpleDNA(length: number): string { return Array.from({ length }, () => Math.floor(Math.random() * 16).toString(16) ).join(""); } // TODO: Replace with your cluster ID const clusterId = "{your cluster id}"; /** * create spore */ const { tx: sporeTx, id: sporeId } = await ccc.spore.createSpore({ signer, data: { contentType: "dob/0", content: ccc.bytesFrom(`{ "dna": "${generateSimpleDNA(16)}" }`, "utf8"), clusterId: clusterId, }, clusterMode: "clusterCell", }); await sporeTx.completeFeeBy(signer, 2000n); const sporeTxHash = await signer.sendTransaction(sporeTx); console.log("Mint DOB tx sent:", sporeTxHash, `Spore ID: ${sporeId}`); await signer.client.waitTransaction(sporeTxHash); console.log( "Mint DOB tx committed:", getExplorerTxUrl(sporeTxHash), `Spore ID: ${sporeId}` ); ``` -------------------------------- ### Setting up Development Environment for Performant WASM on CKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Clones and builds required repositories including AssemblyScript, wabt, WAVM, wavm-aot-generator, ckb-standalone-debugger, ckb-binary-patcher, and ckb-c-stdlib to prepare the environment for developing and testing performant WASM scripts on CKB. ```Shell $ export TOP=$(pwd) $ git clone https://github.com/AssemblyScript/assemblyscript.git $ cd assemblyscript $ git checkout b433bc425633c3df6a4a30c735c91c78526a9eb7 $ npm install $ cd $TOP $ git clone --recursive https://github.com/WebAssembly/wabt $ cd wabt $ git checkout bec78eafbc203d81b9a6d1ce81f5a80dd7bf692a $ mkdir build $ cd build $ cmake .. $ cmake --build . $ cd $TOP $ git clone https://github.com/xxuejie/WAVM $ cd WAVM $ git checkout cb35225feeb4ba1b5a9c73cbbdb07f4cace9b359 $ mkdir build $ cd build # Make sure you are using LLVM 9+, you might need to tweak this path depending # on your environment $ cmake .. -DLLVM_DIR=/usr/lib/llvm-9/lib/cmake/llvm $ cmake --build . $ cd $TOP $ git clone https://github.com/xxuejie/wavm-aot-generator $ cd wavm-aot-generator $ git checkout 8c818747eb19494fc9c5e0289810aa7ad484a22e $ cargo build --release $ cd $TOP $ git clone https://github.com/xxuejie/ckb-standalone-debugger $ cd ckb-standalone-debugger $ git checkout 15e8813b8cb886e95e2c81bbee9f26d47a831850 $ cd bins $ cargo build --release $ cd $TOP $ git clone https://github.com/xxuejie/ckb-binary-patcher $ cd ckb-binary-patcher $ git checkout 930f0b468a8f426ebb759d9da735ebaa1e2f98ba $ cd ckb-binary-patcher $ cargo build --release $ cd $TOP $ git clone https://github.com/nervosnetwork/ckb-c-stdlib $ cd ckb-c-stdlib $ git checkout 693c58163fe37d6abd326c537447260a846375f0 ``` -------------------------------- ### Serialize Single Uint32 in Uint32Vec Fixvec Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/encoding-specs.mdx Shows the serialization of a fixed vector containing a single Uint32 (0x123). The serialized form includes the 4-byte length prefix (1) followed by the serialized item (0x123 in little-endian). ```Hex Bytes 01 00 00 00, 23 01 00 00 ``` -------------------------------- ### Using CCC Molecule Built-in Types (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/ccc-molecule.mdx Provides examples of encoding and decoding common built-in types available in the CCC Molecule module, including boolean, fixed-size byte arrays (Byte16, Byte32), and unsigned integers (Uint8, Uint128LE). ```JavaScript // CCC built-in types console.log(ccc.mol.Bool.decode("0x01")); // true console.log(ccc.mol.Bool.encode(true).toString()); // 1 // All kinds of bytes console.log(ccc.mol.Byte16.encode("0x12345678901234567890123456789012")); console.log(ccc.mol.Byte16.decode(ccc.bytesFrom([18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18]))); console.log(ccc.mol.Byte32.encode("0x1234567890123456789012345678901212345678901234567890123456789012")); console.log(ccc.mol.Byte32.decode(ccc.bytesFrom([18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18,18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18]))); // All kinds of numbers console.log(ccc.mol.Uint8.encode(1).toString()); // 0x01 console.log(ccc.mol.Uint8.decode("0x01")); // 1 console.log(ccc.mol.Uint128LE.decode("0x01000000000000000000000000000000")); // 1 console.log(ccc.mol.Uint128LE.encode(1).toString()); // 0x01000000000000000000000000000000 ``` -------------------------------- ### Initializing CKB-SDK-Java Client Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/java.mdx Code snippet demonstrating how to import necessary classes and initialize the CKB RPC API client, connecting to a specified network URL (Testnet, Devnet, or Mainnet). ```Java import org.nervos.ckb.service.Api; import org.nervos.ckb.service.CkbRpcApi; String testnetUrl = "https://testnet.ckb.dev"; // Testnet String devnetUrl = "http://127.0.0.1:8114"; // Devnet String mainnetUrl = "https://mainnet.ckb.dev/rpc"; // Mainnet // Connect to Testnet CkbRpcApi ckbApi = new Api(testnetUrl); ``` -------------------------------- ### Create JavaScript Source and Build Directories (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Navigates into the project directory, creates a 'js' directory for source files, a 'build' subdirectory within 'js' for compiled output, and creates an empty 'hello.js' file. ```Bash cd ckb-js-script mkdir js/build touch js/hello.js ``` -------------------------------- ### Creating HTLC Cell Transaction (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This script demonstrates how to construct and send a transaction to create an HTLC cell on the CKB network. It calculates the lock hash, loads available cells, defines the transaction inputs and outputs, serializes the HTLC arguments using a Molecule schema, signs the transaction with a private key, and broadcasts it to the network. It includes logic for calculating capacity, fee, and handling cell dependencies. ```JavaScript const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const htlcCellCapacity = 200000000000n const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcArgsType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcArgs")) const htlcScriptArgs = htlcArgsType.serialize([ ['a', hexStringToHexStringArray(lockHashA)], ['b', hexStringToHexStringArray(lockHashB)], ['hash', hexStringToHexStringArray('0x' + crc32('i am a secret'))] ]) const transaction = { version: '0x0', cellDeps: [ { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs: [ { lock: { codeHash: utils.bytesToHex(duktapeHash), hashType: 'data', args: htlcScriptArgs }, type: null, capacity: '0x' + htlcCellCapacity.toString(16) }, { lock: lockScript, type: null, capacity: '0x' + (totalCapacity - fee - htlcCellCapacity).toString(16) } ], witnesses: [ { lock: '', inputType: '', outputType: '' } ], outputsData: [ '0x', '0x' ] } const signedTransaction = ckb.signTransaction(privateKey)(transaction) const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('create_htlc_cell_result.txt', txHash) } run() ``` -------------------------------- ### Debugging Transaction with OffCKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Uses the offckb debug command with a transaction hash to analyze the execution of the transaction on the Devnet, showing script run results and cycle consumption. ```sh offckb debug --tx-hash 0x252305141e6b7db81f7da94b098493a36b756fe9d5d4436c9d7c966882bc0b38 ``` -------------------------------- ### Defining Role and Character Tables Molecule C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/example-role-playing-game.mdx Defines the `Class` type for character classes and the main character types, `Hero` and `Monster`, using Molecule's `table` type. The `Hero` table includes fields for class, level, experience, stats (hp, mp, base_damage), attributes (`Attributes`), and skills (`Skills`), importing necessary types. ```c import attributes; import skills; import common/basic_types; // We have only 3 classes: Fighter, Ranger and Mage. A `byte` is enough. array Class [byte; 1]; table Hero { class: Class, level: Uint8, experiences: Uint32, hp: Uint16, mp: Uint16, base_damage: Uint16, attrs: Attributes, skills: Skills, } table Monster { hp: Uint16, damage: Uint16, } ``` -------------------------------- ### Unlock HTLC via Timeout (Wrong Public Key) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Demonstrates attempting to unlock an HTLC cell using the `unlock_via_timeout.js` script with sufficient time but an incorrect public key. As expected, this scenario also results in a validation failure. ```Shell ./unlock_via_timeout.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" \ 0x665ccfab2d854afa035f4697a2301f2bad9d4aa86506090b104f8ed18772ca01 \ true ``` -------------------------------- ### Unlock HTLC via Secret String (Invalid Secret) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Demonstrates attempting to unlock an HTLC cell using the `unlock_via_secret_string.js` script with an incorrect secret string. This is expected to fail validation, as indicated by the CKB debug logs. ```Shell ./unlock_via_secret_string.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \ "http://127.0.0.1:8114/" \ "invalid secret" \ true ``` -------------------------------- ### Main C Program for Fibonacci Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-4.md Entry point for the C program that calculates Fibonacci using a WebAssembly function. It takes an argument from the command line, initializes the WASM runtime, calls the `fib` function, and returns the result. ```C int main(int argc, char** argv) { if (argc < 2) return 2; u8 x = atoi(argv[1]); Z_envZ_abortZ_viiii = &env_abort; init(); u8 result = Z_fibZ_ii(x); return result; } ``` -------------------------------- ### Defining Basic Types Molecule C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/example-role-playing-game.mdx Defines fundamental data types used in the game schema, such as aliases for single bytes (`AttrValue`, `SkillLevel`) and fixed-size unsigned integers (`Uint8`, `Uint16`, `Uint32`), using Molecule's `array` type. Includes comments explaining the purpose and limitations. ```c // AttrValue is an alias of `byte`. // // Since Molecule data are strongly-typed, it can gives compile time guarantees // that the right type of value is supplied to a method. // // In this example, we use this alias to define an unsigned integer which // has an upper limit: 100. // So it's easy to distinguish between this type and a real `byte`. // Of course, the serialization wouldn't do any checks for this upper limit // automatically. You have to implement it by yourself. // // **NOTE**: // - This feature is dependent on the exact implementation. // In official Rust generated code, we use new type to implement this feature. array AttrValue [byte; 1]; // SkillLevel is an alias of `byte`, too. // // Each skill has only 10 levels, so we use another alias of `byte` to distinguish. array SkillLevel [byte; 1]; // Define several unsigned integers. array Uint8 [byte; 1]; array Uint16 [byte; 2]; array Uint32 [byte; 4]; ``` -------------------------------- ### Loading Cell Data Fields via CKB Syscall in Debugger (Duktape) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This snippet demonstrates using CKB syscalls in the Duktape debugger to access specific fields of cells within the transaction. It shows how to get constants like `CKB.SOURCE.OUTPUT` and `CKB.CELL.CAPACITY` and how to use `CKB.load_cell_by_field` to retrieve the capacity of a cell, converting the result to hex. ```Bash duk> print(CKB.SOURCE.OUTPUT) 2 = undefined duk> print(CKB.CELL.CAPACITY) 0 = undefined duk> capacity_field = CKB.load_cell_by_field(0, 0, CKB.SOURCE.OUTPUT, CKB.CELL.CAPACITY) = [object ArrayBuffer] duk> buf2hex(capacity_field) = 00e40b5402000000 ``` -------------------------------- ### Executing & Viewing HTLC Unlock Script (Timeout) (Shell & JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This snippet shows the shell command to navigate to the script directory and view the content of the JavaScript file used to unlock an HTLC-guarded cell after the timeout period has passed. The JavaScript code initializes the CKB SDK, loads necessary dependencies, retrieves cell and header information, constructs the transaction, and prepares the witness for timeout unlocking. ```Shell $ cd $TOP/htlc-runner $ cat unlock_via_timeout.js ``` ```JavaScript #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const crc32 = require('crc32') const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 8) { console.log(`Usage: ${process.argv[1]}
`) process.exit(1) } const deployedTxHash = process.argv[2] const htlcCellTxHash = process.argv[3] const privateKey = process.argv[4] const nodeUrl = process.argv[5] const headerHash = process.argv[6] const dryrun = process.argv[7] === 'true' const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() const htlcCellTx = await ckb.rpc.getTransaction(htlcCellTxHash) const htlcCellHeaderHash = htlcCellTx.txStatus.blockHash const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const htlcCellCapacity = 200000000000n const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcWitnessType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcWitness")) const htlcWitness = htlcWitnessType.serialize([ ['s', []], ['i', ['0x1', '0x0', '0x0', '0x0']] ]) const transaction = { version: '0x0', cellDeps: [ // Due to the requirement of load0 duktape binary, JavaScript source cell // should be the first one in cell deps { outPoint: { txHash: deployedTxHash, index: "0x1" }, depType: 'code' }, { outPoint: { txHash: deployedTxHash, index: "0x0" }, depType: 'code' }, { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [ htlcCellHeaderHash, headerHash, ], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs: [ { lock: lockScript, type: null, capacity: '0x' + (totalCapacity + htlcCellCapacity - fee).toString(16) } ], witnesses: unspentCells.map(_cell => '0x'), outputsData: [ '0x', '0x' ] } ``` -------------------------------- ### List OffCKB Configuration Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Use this command to display the current OffCKB configuration, including RPC URL, config path, and data path for different networks like devnet. ```bash offckb config list ``` -------------------------------- ### Subscribing to CKB Updates via TCP RPC (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/rpcs.mdx This command demonstrates how to establish a persistent TCP connection to a CKB node using netcat. It sends an initial JSON RPC request (shown as 'get_tip_block_number' in the example) and keeps the connection open, which is necessary for receiving streaming updates like those from a subscription. ```shell cat <(echo '{ "id": 2, "jsonrpc": "2.0", "method": "get_tip_block_number", "params": [] }' \ | tr -d '\n' \ | sed -e "s/$/\n/") -\ | nc localhost 18114 ``` -------------------------------- ### Start of Issue Token Function - TypeScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/create-token.mdx Begins the `issueToken` function, which takes the issuer's private key and token amount. It initializes a CKB signer, retrieves the issuer's lock script, and constructs the arguments for the xUDT script by hashing the lock script (serving as the unique token ID) and appending a placeholder ('00000000'). It then prepares to create the xUDT type script. ```ts export async function issueToken(privKey: string, amount: string) { const signer = new ccc.SignerCkbPrivateKey(cccClient, privKey); const lockScript = (await signer.getAddressObjSecp256k1()).script; const xudtArgs = lockScript.hash() + "00000000"; const typeScript = await ccc.Script.fromKnownScript( signer.client, ccc.KnownScript.XUdt, xudtArgs ); ... } ``` -------------------------------- ### Execute CKB Script with Debugger and Dump Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md This command executes the `dump_load0_nocleanup` script using the `runner.rb` helper, piping the execution to the `ckb-debugger` and saving the trace to `dump0.bin`. The output includes debugging information and the total cycles consumed. ```Shell $ cd $TOP $ RUST_LOG=debug ./runner.rb ckb-duktape/build/dump_load0_nocleanup script.bin dump0.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input -d dump0.bin DEBUG:: script group: Byte32(0x06034ffb00fec553882c6a9c7614333a728828772d3c236a7f8fa6af60669538) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 7856033 Transfer cycles: 67348, running cycles: 7788685 ``` -------------------------------- ### Sending/Dry-Running CKB Transaction (JS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This JavaScript snippet constructs, signs, and either dry-runs or sends a CKB transaction. It adds an input, prepares witness data, signs with a private key, and interacts with the CKB RPC client for validation or broadcasting. Includes error handling for dry runs. ```JavaScript transaction.inputs.push({ previousOutput: { txHash: htlcCellTxHash, index: "0x0" }, since: '0x0' }) transaction.witnesses[0] = { lock: '', inputType: '', outputType: '' } const signedTransaction = ckb.signTransaction(privateKey)(transaction) signedTransaction.witnesses.push(htlcWitness) if (dryrun) { try { const result = await ckb.rpc.dryRunTransaction(signedTransaction) console.log(`Dry run success result: ${JSON.stringify(result, null, 2)}`) } catch (e) { console.log(`Dry run failure result: ${JSON.stringify(JSON.parse(e.message), null, 2)}`) } } else { const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('unlock_via_timeout_result.txt', txHash) } } ``` -------------------------------- ### Starting CKB Debugger with Transaction File (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This bash command launches the `ckb-debugger` tool, specifying the transaction file generated by the dumper ("duktape.json"). It also configures the debugger to focus on a specific cell (index 0) within the transaction's output cells and targets the 'type' script group. ```Bash $ ckb-debugger --tx-file duktape.json --cell-index 0 --cell-type output --script-group-type type ``` -------------------------------- ### Creating UDT Cell and Getting Outpoint (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-3.md This JavaScript snippet uses the Lumos library to create a transaction skeleton for a UDT cell and extracts the hexadecimal representation of the outpoint of the first input cell. This outpoint is required as an argument for the UDT script during the token issuance transaction. ```javascript > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton, [wallet.address], wallet2.address, "1820" + "00000000"); > const blockchain = require("@ckb-lumos/base").blockchain; > const outPointBuf = blockchain.OutPoint.pack(txSkeleton.get("inputs").first().outPoint); > const outPointHex = Buffer.from(outPointBuf).toString("hex"); > outPointHex 6a5f904a6f6ec270b6dde3add221aa8a82120e2e98ea6dac59160dd09359084201000000 ``` -------------------------------- ### Unlock HTLC via Secret String (Invalid Public Key) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Shows attempting to unlock an HTLC cell using the `unlock_via_secret_string.js` script with the correct secret but an invalid public key. This scenario is also expected to result in a validation failure. ```Shell ./unlock_via_secret_string.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d \ "http://127.0.0.1:8114/" \ "i am a secret" \ true ``` -------------------------------- ### Building CKB Transfer Transaction (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/transfer-ckb.mdx This snippet shows the initial part of the `transfer` function implementation. It initializes a signer with the private key, gets the recipient's lock script, and builds a transaction object using `ccc.Transaction.from`. It then sets the capacity for the output cell(s) based on the transfer amount. Requires the CCC SDK. ```TypeScript export async function transfer( toAddress: string, amountInCKB: string, signerPrivateKey: string ): Promise { const signer = new ccc.SignerCkbPrivateKey(cccClient, signerPrivateKey); const { script: toLock } = await ccc.Address.fromString(toAddress, cccClient); // Build the full transaction to estimate the fee const tx = ccc.Transaction.from({ outputs: [{ lock: toLock }], outputsData: [], }); // CCC transactions are easy to be edited tx.outputs.forEach((output, i) => { if (output.capacity > ccc.fixedPointFrom(amountInCKB)) { alert(`Insufficient capacity at output ${i} to store data`); return; } output.capacity = ccc.fixedPointFrom(amountInCKB); }); // .... } ``` -------------------------------- ### Compiling Duktape for CKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This snippet provides the necessary bash commands to clone the ckb-duktape repository, initialize and update submodules, and compile the Duktape C source code into RISC-V executable binaries suitable for the CKB VM using a Docker container with the required toolchain. ```bash $ git clone https://github.com/xxuejie/ckb-duktape.git $ cd ckb-duktape $ git submodule init $ git submodule update $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash root@0d31cad7a539:~# cd /code root@0d31cad7a539:/code# make riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/entry.c -c -o build/entry.o riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror duktape/duktape.c -c -o build/duktape.o riscv64-unknown-elf-gcc build/entry.o build/duktape.o -o build/duktape -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/repl.c -c -o build/repl.o riscv64-unknown-elf-gcc build/repl.o build/duktape.o -o build/repl -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/dump_load.c -c -o build/dump_load.o riscv64-unknown-elf-gcc build/dump_load.o build/duktape.o -o build/dump_load -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s gcc -Wall -Werror -Iduktape -O3 c/native_dump_bytecode.c duktape/duktape.c -o build/native_dump_bytecode -lm riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Ischema -Ideps/ckb-c-stdlib -Ideps/ckb-c-stdlib/molecule -Wall -Werror c/dump_load_nocleanup.c -c -o build/dump_load_nocleanup.o riscv64-unknown-elf-gcc build/dump_load_nocleanup.o build/duktape.o -o build/dump_load_nocleanup -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s gcc -Wall -Werror -Ischema -Ideps/ckb-c-stdlib/molecule -O3 c/native_args_assembler.c -o build/native_args_assembler root@0d31cad7a539:/code# exit exit $ ls build/ duktape dump_load dump_load_nocleanup entry.o native_dump_bytecode repl.o duktape.o dump_load.o dump_load_nocleanup.o native_args_assembler repl ``` -------------------------------- ### Get Tip Block Number via WebSocket RPC Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/rpcs.mdx Sends a standard JSON-RPC request payload over the established WebSocket connection to query the current tip block number of the CKB chain. The response will contain the block number in hex format. ```JSON {"id": 2, "jsonrpc": "2.0", "method": "get_tip_block_number", "params": []} ``` -------------------------------- ### List Pre-Funded OffCKB Accounts Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Shows the command to print details of the 20 pre-funded development accounts included with OffCKB. ```bash offckb accounts ``` -------------------------------- ### Implementing CKB HTLC Script Logic in JavaScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This JavaScript code implements the core logic for a CKB HTLC script. It uses the Molecule library to deserialize script arguments and witness data, which define the conditions for unlocking the funds (either providing a secret hash or waiting for a timelock). It also includes helper functions for data conversion and interacts with the CKB environment via CKB built-in functions. ```javascript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = new Molecule(schema.declarations[scriptTypeIndex]) // Write your script logic here. const customSchema = require('./htlc-combined.json') const customNames = customSchema.declarations.map(d => d.name) const htlcArgsIndex = customNames.indexOf('HtlcArgs') const htlcArgsType = new Molecule(customSchema.declarations[htlcArgsIndex]) function bytesToHex(b) { return "0x" + Array.prototype.map.call( new Uint8Array(b), function(x) { return ('00' + x.toString(16)).slice(-2) } ).join('') } function hexStringArrayToString(a) { let s = ""; for (let i = 0; i < a.length; i++) { s = s + String.fromCharCode(parseInt(a[i])) } return s } function hexStringArrayToHexString(a) { let s = "0x"; for (let i = 0; i < a.length; i++) { s = s + a[i].substr(2) } return s } function parseLittleEndianHexStringArray(a) { let v = 0 const l = a.length for (let i = 0; i < l; i++) { v = (v << 8) | parseInt(a[l - i - 1]) } return v } const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) // Load and parse witness data using the same method as above const htlcWitnessIndex = customNames.indexOf('HtlcWitness') const htlcWitnessType = new Molecule(customSchema.declarations[htlcWitnessIndex]) const rawWitness = CKB.load_witness(0, 0, CKB.SOURCE.GROUP_INPUT) if (typeof rawWitness === 'number') { throw new Error(`Invalid response when loading witness: ${rawWitness}`) } const htlcWitness = htlcWitnessType.deserialize(bytesToHex(rawWitness)) let lockHashToMatch; if (htlcWitness[0][1].length > 0) { // Test secret string hash const crc32 = require('crc32') const hash = '0x' + crc32(hexStringArrayToString(htlcWitness[0][1])) if (hash !== hexStringArrayToHexString(htlcArgs[2][1])) { throw new Error(`Invalid secret string!`) } lockHashToMatch = hexStringArrayToHexString(htlcArgs[0][1]) } else { // Test header block const headerTypeIndex = names.indexOf('Header') const headerType = new Molecule(schema.declarations[headerTypeIndex]) // Load header for current input first const rawInputHeader = CKB.load_header(0, 0, CKB.SOURCE.GROUP_INPUT) if (typeof rawWitness === 'number') { throw new Error(`Invalid response when loading input header: ${rawInputHeader}`) } const inputHeader = headerType.deserialize(bytesToHex(rawInputHeader)) const inputHeaderNumber = parseLittleEndianHexStringArray(inputHeader[0][1][3][1]) const targetHeaderIndex = parseLittleEndianHexStringArray(htlcWitness[1][1]) const rawTargetHeader = CKB.load_header(0, targetHeaderIndex, CKB.SOURCE.HEADER_DEP) if (typeof rawTargetHeader === 'number') { throw new Error(`Invalid response when loading target header: ${rawTargetHeader}`) } const targetHeader = headerType.deserialize(bytesToHex(rawTargetHeader)) const targetHeaderNumber = parseLittleEndianHexStringArray(targetHeader[0][1][3][1]) if (targetHeaderNumber < inputHeaderNumber + 100) { throw new Error(`Timeout period has not reached!`) } lockHashToMatch = hexStringArrayToHexString(htlcArgs[1][1]) } // Now we know which lock hash to test against, we look for an input cell // with the specified lock hash let i = 0 while (true) { const rawHash = CKB.load_cell_by_field(0, i, CKB.SOURCE.INPUT, CKB.CELL.LOCK_HASH) if (rawHash == CKB.CODE.INDEX_OUT_OF_BOUND) { throw new Error(`Cannot find input cell using lock hash ${lockHashToMatch}`) } if (typeof rawHash === 'number') { throw new Error(`Invalid response when loading input cell: ${rawHash}`) } if (bytesToHex(rawHash) == lockHashToMatch) { break } i += 1 } ``` -------------------------------- ### Assemble Duktape Script Args (Simple JS) - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Uses a Docker container with the CKB RISC-V toolchain to run `native_args_assembler`. It creates a simple JavaScript file (`test.js`) and uses the assembler to generate the hexadecimal script arguments required for the duktape script. ```Bash docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash cd /code echo "CKB.debug(\"I'm running in JS\")" > test.js ./build/native_args_assembler -f test.js ``` -------------------------------- ### CKB C Script Example: Carrot Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This C code implements a simple CKB script that iterates through output cells and checks if their data matches the string "carrot". It uses CKB syscalls like `ckb_load_cell_data` and standard library functions like `memset` and `memcmp`. It contains an intentional bug for debugging demonstration. ```C #include #include "ckb_syscalls.h" int main(int argc, char* argv[]) { int ret; size_t index = 0; uint64_t len = 0; unsigned char buffer[6]; while (1) { len = 6; memset(buffer, 0, 6); ret = ckb_load_cell_data(buffer, &len, 0, index, CKB_SOURCE_OUTPUT); if (ret == CKB_INDEX_OUT_OF_BOUND) { break; } int cmp = memcmp(buffer, "carrot", 6); if (cmp) { return -1; } index++; } return 0; } ``` -------------------------------- ### Unlock HTLC via Timeout (Insufficient Time) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Shows attempting to unlock an HTLC cell using the `unlock_via_timeout.js` script with a block hash corresponding to a block number (409) that is before the configured timeout period (block 399). This is expected to fail validation. ```Shell ./unlock_via_timeout.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d \ "http://127.0.0.1:8114/" \ 0xe93ebb311d156847fbcdc159d1fa3c38f12613121e51582272d909379c4d1a60 \ true ``` -------------------------------- ### Unlock HTLC via Timeout (Sufficient Time) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md Illustrates unlocking an HTLC cell using the `unlock_via_timeout.js` script with a block hash corresponding to a block number (510) that is after the configured timeout period (block 399). This method is for demo purposes and is expected to succeed. ```Shell ./unlock_via_timeout.js \ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \ 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d \ "http://127.0.0.1:8114/" \ 0x665ccfab2d854afa035f4697a2301f2bad9d4aa86506090b104f8ed18772ca01 \ true ``` -------------------------------- ### Add Required Dependencies (Cargo.toml) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/ckb-script-ipc.mdx Add the necessary crates (`ckb-script-ipc`, `ckb-script-ipc-common`, `serde`) to your project's `Cargo.toml` file. Remember to replace the version placeholders (`...`) with the latest available versions. ```TOML ckb-script-ipc = { version = "..." } ckb-script-ipc-common = { version = "..." } serde = { version = "...", default-features = false, features = ["derive"] } ``` -------------------------------- ### Deploying ckb-js-vm Script (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Command and response for deploying the `ckb-js-vm` binary to the CKB devnet using `offckb deploy`. This makes the VM available as a script on-chain. ```sh offckb deploy --target ./deps/ckb-js-vm --type-id ``` ```sh wait for tx confirmed on-chain... tx committed. ckb-js-vm deployment.toml file /Library/Application Support/offckb-nodejs/devnet/contracts/ckb-js-vm/deployment.toml generated successfully. ckb-js-vm migration json file /Library/Application Support/offckb-nodejs/devnet/contracts/ckb-js-vm/migrations/2024-11-18-195031.json generated successfully. done. ``` -------------------------------- ### CKB Script to Check Cell Data (Carrot Forbidden) - C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md This CKB script demonstrates how to read cell data using the `ckb_load_cell_data` syscall. It iterates through the output cells of a transaction, reads the first 6 bytes of data from each, and returns -1 (failure) if any cell's data starts with the string "carrot". It requires including `memory.h` and `ckb_syscalls.h`. ```C #include #include "ckb_syscalls.h" int main(int argc, char* argv[]) { int ret; size_t index = 0; uint64_t len = 0; /* (1) */ unsigned char buffer[6]; while (1) { len = 6; memset(buffer, 0, 6); ret = ckb_load_cell_data(buffer, &len, 0, index, CKB_SOURCE_OUTPUT); /* (2) */ if (ret == CKB_INDEX_OUT_OF_BOUND) { /* (3) */ break; } if (memcmp(buffer, "carrot", 6) == 0) { return -1; } index++; } return 0; } ``` -------------------------------- ### Create Project Directory (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Initializes the main project directory named 'ckb-js-script' where all project files and dependencies will reside. ```Shell mkdir ckb-js-script ``` -------------------------------- ### Set Script Type on Output Cell using Lumos Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This JavaScript snippet demonstrates how to create a new transaction that utilizes the deployed script. It starts with a new transaction skeleton, transfers capacity to an output cell, and then updates that output cell's `type` field to the previously created `carrotTypeScript` object. This indicates that the script should be executed when this cell is consumed. ```js > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address], wallet2.address,"100" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.cellOutput.type = carrotTypeScript; return outputs; }); ``` -------------------------------- ### Creating New Project with bun (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Uses the `create-ccc-app` CLI tool via bun to quickly scaffold a new project with built-in CCC wallet connection support. ```Bash bunx create-ccc-app ``` -------------------------------- ### Defining HTLC Molecule Structures Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Defines the Molecule structures HtlcArgs and HtlcWitness used for custom arguments in an HTLC CKB script. HtlcArgs holds public key hashes and a hash value, while HtlcWitness holds either a secret string or a block header index. ```Molecule array Uint32 [byte; 4]; array Byte32 [byte; 32]; vector Bytes ; struct HtlcArgs { a: Byte32, b: Byte32, hash: Uint32, } table HtlcWitness { s: Bytes, i: Uint32, } ``` -------------------------------- ### Initialize CKB Node for Testnet Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-testnet-node.mdx Run the initialization command for the CKB node, specifying the 'testnet' chain to connect to the Pudge Testnet. ```bash ckb init --chain testnet ``` -------------------------------- ### Call Restricted RPC Method (Bash/Text) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-public-rpc-node.mdx Attempts to call the restricted clear_tx_pool RPC method using curl via the Nginx proxy. This example shows that the proxy is configured to block such methods, returning a "This method has been banned" message. Requires curl and the Nginx proxy to be running. ```bash echo '{ "id": 2, "jsonrpc": "2.0", "method": "clear_tx_pool", "params": [] }' | tr -d '\n' | curl -H 'content-type: application/json' -d @- \ http://192.168.1.100:80 ``` ```text This method has been banned. ``` -------------------------------- ### Getting Account Balance by Address (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/transfer-ckb.mdx This function queries the balance of a CKB account given its address. It converts the address string to a CCC Address object and then uses the CCC SDK client to fetch the balance associated with the account's Lock Script. The balance is returned in Shannon units. ```TypeScript export async function capacityOf(address: string): Promise { const addr = await ccc.Address.fromString(address, cccClient); let balance = await cccClient.getBalance([addr.script]); return balance; } ``` -------------------------------- ### Test HTLC Unlock via Secret (Invalid Secret) - CKB Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Executes the `unlock_via_secret_string.js` script with an invalid secret string to demonstrate the expected validation failure when the secret is incorrect. This test verifies that the script correctly rejects unlocking attempts with an invalid secret. ```Shell $ ./unlock_via_secret_string.js \\ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \\ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \\ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \\ "http://127.0.0.1:8114/" \\ "invalid secret" \\ true ``` -------------------------------- ### Constructing CKB Transaction for HTLC Secret Unlock (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This JavaScript code snippet demonstrates how to construct a CKB transaction to unlock an HTLC cell using the correct secret string. It includes setting up cell dependencies, inputs, outputs, and serializing the HTLC witness data with the secret using Molecule. The snippet also shows how to sign the transaction and perform a dry run or send it. ```JavaScript ['s', stringToHexStringArray(secretString)], ['i', ['0x0', '0x0', '0x0', '0x0']] ]) const transaction = { version: '0x0', cellDeps: [ // Due to the requirement of load0 duktape binary, JavaScript source cell // should be the first one in cell deps { outPoint: { txHash: deployedTxHash, index: "0x1" }, depType: 'code' }, { outPoint: { txHash: deployedTxHash, index: "0x0" }, depType: 'code' }, { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs: [ { lock: lockScript, type: null, capacity: '0x' + (totalCapacity + htlcCellCapacity - fee).toString(16) } ], witnesses: unspentCells.map(_cell => '0x'), outputsData: [ '0x', '0x' ] } transaction.inputs.push({ previousOutput: { txHash: htlcCellTxHash, index: "0x0" }, since: '0x0' }) transaction.witnesses[0] = { lock: '', inputType: '', outputType: '' } const signedTransaction = ckb.signTransaction(privateKey)(transaction) signedTransaction.witnesses.push(htlcWitness) if (dryrun) { try { const result = await ckb.rpc.dryRunTransaction(signedTransaction) console.log(`Dry run success result: ${JSON.stringify(result, null, 2)}`) } catch (e) { console.log(`Dry run failure result: ${JSON.stringify(JSON.parse(e.message), null, 2)}`) } } else { const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('unlock_via_secret_string_result.txt', txHash) } } run() ``` -------------------------------- ### Deploying hello.bc Script (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Command and response for deploying the compiled `hello.bc` JavaScript code to the CKB devnet using `offckb deploy`. This makes the JS code available as a script on-chain. ```sh offckb deploy --target ./js/build/hello.bc --type-id ``` ```sh wait for tx confirmed on-chain... tx committed. hello.bc deployment.toml file /Library/Application Support/offckb-nodejs/devnet/contracts/hello.bc/deployment.toml generated successfully. hello.bc migration json file /Library/Application Support/offckb-nodejs/devnet/contracts/hello.bc/migrations/2024-11-18-195031.json generated successfully. done. ``` -------------------------------- ### Implementing CKB Hash Lock Script in Rust Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/simple-lock.mdx This Rust code defines the on-chain logic for a CKB hash lock. It loads the script arguments to get the expected hash, retrieves the preimage from the first input's witness, hashes the preimage using Blake2b-256, and compares the resulting hash with the expected hash. It returns 0 on success or a custom error code on failure. ```Rust #![no_std] #![cfg_attr(not(test), no_main)] #[cfg(test)] extern crate alloc; use ckb_hash::blake2b_256; use ckb_std::ckb_constants::Source; #[cfg(not(test))] use ckb_std::default_alloc; use ckb_std::error::SysError; #[cfg(not(test))] ckb_std::entry!(program_entry); #[cfg(not(test))] default_alloc!(); #[repr(i8)] pub enum Error { IndexOutOfBound = 1, ItemMissing, LengthNotEnough, Encoding, // Add customized errors here... CheckError, UnMatch, } impl From for Error { fn from(err: SysError) -> Self { match err { SysError::IndexOutOfBound => Self::IndexOutOfBound, SysError::ItemMissing => Self::ItemMissing, SysError::LengthNotEnough(_) => Self::LengthNotEnough, SysError::Encoding => Self::Encoding, SysError::Unknown(err_code) => panic!("unexpected sys error {}", err_code), } } } pub fn program_entry() -> i8 { ckb_std::debug!("This is a sample contract!"); match check_hash() { Ok(_) => 0, Err(err) => err as i8, } } pub fn check_hash() -> Result<(), Error> { let script = ckb_std::high_level::load_script()?; let expect_hash = script.args().raw_data().to_vec(); let witness_args = ckb_std::high_level::load_witness_args(0, Source::GroupInput)?; let preimage = witness_args .lock() .to_opt() .ok_or(Error::CheckError)? .raw_data(); let hash = blake2b_256(preimage.as_ref()); if hash.eq(&expect_hash.as_ref()) { Ok(()) } else { Err(Error::UnMatch) } } ``` -------------------------------- ### Test HTLC Unlock via Timeout (Success) - CKB Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Executes the `unlock_via_timeout.js` script using a block hash corresponding to a block number (510) that is past the required timeout period, demonstrating successful unlocking via timeout. This test validates the timeout-based unlocking mechanism. ```Shell $ ./unlock_via_timeout.js \\ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \\ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \\ 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d \\ "http://127.0.0.1:8114/" \\ 0x665ccfab2d854afa035f4697a2301f2bad9d4aa86506090b104f8ed18772ca01 \\ true ``` -------------------------------- ### Create Full-Stack OffCKB Project Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Generate a new project from a predefined boilerplate that includes both a script (smart contract) and a frontend application for CKB development. ```bash offckb create ``` -------------------------------- ### Dumping CKB Transaction JSON (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md This bash command uses the ckb-transaction-dumper utility to process a raw transaction JSON file ("duktape-tx.json"). It outputs a new JSON file ("duktape.json") which is formatted for use with the ckb-debugger. Requires the ckb-transaction-dumper tool to be installed and the input JSON file to exist. ```Bash ckb-transaction-dumper -t duktape-tx.json -o duktape.json ``` -------------------------------- ### Implementing CKB HTLC Script Logic - JavaScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This JavaScript code implements the core logic for a CKB HTLC contract. It uses the Molecule library to deserialize script arguments and witness data based on predefined schemas. The script handles two paths: one based on revealing a secret string (verified using CRC32) and another based on a timeout period (verified by comparing block numbers from headers). It interacts with the CKB environment to load script, witness, header, and cell data. ```javascript const { Molecule } = require('molecule-javascript') const schema = require('../schema/blockchain-combined.json') const names = schema.declarations.map(declaration => declaration.name) const scriptTypeIndex = names.indexOf('Script') const scriptType = new Molecule(schema.declarations[scriptTypeIndex]) // Write your script logic here. const customSchema = require('./htlc-combined.json') const customNames = customSchema.declarations.map(d => d.name) const htlcArgsIndex = customNames.indexOf('HtlcArgs') const htlcArgsType = new Molecule(customSchema.declarations[htlcArgsIndex]) function bytesToHex(b) { return "0x" + Array.prototype.map.call( new Uint8Array(b), function(x) { return ('00' + x.toString(16)).slice(-2) } ).join('') } function hexStringArrayToString(a) { let s = ""; for (let i = 0; i < a.length; i++) { s = s + String.fromCharCode(parseInt(a[i])) } return s } function hexStringArrayToHexString(a) { let s = "0x"; for (let i = 0; i < a.length; i++) { s = s + a[i].substr(2) } return s } function parseLittleEndianHexStringArray(a) { let v = 0 const l = a.length for (let i = 0; i < l; i++) { v = (v << 8) | parseInt(a[l - i - 1]) } return v } const current_script = scriptType.deserialize(bytesToHex(CKB.load_script(0))) const args = hexStringArrayToHexString(current_script[2][1]) const htlcArgs = htlcArgsType.deserialize(args) // Load and parse witness data using the same method as above const htlcWitnessIndex = customNames.indexOf('HtlcWitness') const htlcWitnessType = new Molecule(customSchema.declarations[htlcWitnessIndex]) const rawWitness = CKB.load_witness(0, 0, CKB.SOURCE.GROUP_INPUT) if (typeof rawWitness === 'number') { throw new Error(`Invalid response when loading witness: ${rawWitness}`) } const htlcWitness = htlcWitnessType.deserialize(bytesToHex(rawWitness)) let lockHashToMatch; if (htlcWitness[0][1].length > 0) { // Test secret string hash const crc32 = require('crc32') const hash = '0x' + crc32(hexStringArrayToString(htlcWitness[0][1])) if (hash !== hexStringArrayToHexString(htlcArgs[2][1])) { throw new Error(`Invalid secret string!`) } lockHashToMatch = hexStringArrayToHexString(htlcArgs[0][1]) } else { // Test header block const headerTypeIndex = names.indexOf('Header') const headerType = new Molecule(schema.declarations[headerTypeIndex]) // Load header for current input first const rawInputHeader = CKB.load_header(0, 0, CKB.SOURCE.GROUP_INPUT) if (typeof rawWitness === 'number') { throw new Error(`Invalid response when loading input header: ${rawInputHeader}`) } const inputHeader = headerType.deserialize(bytesToHex(rawInputHeader)) const inputHeaderNumber = parseLittleEndianHexStringArray(inputHeader[0][1][3][1]) const targetHeaderIndex = parseLittleEndianHexStringArray(htlcWitness[1][1]) const rawTargetHeader = CKB.load_header(0, targetHeaderIndex, CKB.SOURCE.HEADER_DEP) if (typeof rawTargetHeader === 'number') { throw new Error(`Invalid response when loading target header: ${rawTargetHeader}`) } const targetHeader = headerType.deserialize(bytesToHex(rawTargetHeader)) const targetHeaderNumber = parseLittleEndianHexStringArray(targetHeader[0][1][3][1]) if (targetHeaderNumber < inputHeaderNumber + 100) { throw new Error(`Timeout period has not reached!`) } lockHashToMatch = hexStringArrayToHexString(htlcArgs[1][1]) } // Now we know which lock hash to test against, we look for an input cell // with the specified lock hash let i = 0 while (true) { const rawHash = CKB.load_cell_by_field(0, i, CKB.SOURCE.INPUT, CKB.CELL.LOCK_HASH) if (rawHash == CKB.CODE.INDEX_OUT_OF_BOUND) { throw new Error(`Cannot find input cell using lock hash ${lockHashToMatch}`) } if (typeof rawHash === 'number') { throw new Error(`Invalid response when loading input cell: ${rawHash}`) } if (bytesToHex(rawHash) == lockHashToMatch) { break } i += 1 } ``` -------------------------------- ### Constructing & Sending HTLC Unlock Transaction (Secret String) (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This JavaScript code constructs a CKB transaction to unlock an HTLC-guarded cell using a secret string. It defines cell dependencies, inputs, outputs, and witnesses, signs the transaction with a private key, and then either performs a dry run or sends the transaction to the CKB network. ```JavaScript ]) const transaction = { version: '0x0', cellDeps: [ // Due to the requirement of load0 duktape binary, JavaScript source cell // should be the first one in cell deps { outPoint: { txHash: deployedTxHash, index: "0x1" }, depType: 'code' }, { outPoint: { txHash: deployedTxHash, index: "0x0" }, depType: 'code' }, { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs: [ { lock: lockScript, type: null, capacity: '0x' + (totalCapacity + htlcCellCapacity - fee).toString(16) } ], witnesses: unspentCells.map(_cell => '0x'), outputsData: [ '0x', '0x' ] } transaction.inputs.push({ previousOutput: { txHash: htlcCellTxHash, index: "0x0" }, since: '0x0' }) transaction.witnesses[0] = { lock: '', inputType: '', outputType: '' } const signedTransaction = ckb.signTransaction(privateKey)(transaction) signedTransaction.witnesses.push(htlcWitness) if (dryrun) { try { const result = await ckb.rpc.dryRunTransaction(signedTransaction) console.log(`Dry run success result: ${JSON.stringify(result, null, 2)}`) } catch (e) { console.log(`Dry run failure result: ${JSON.stringify(JSON.parse(e.message), null, 2)}`) } } else { const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('unlock_via_secret_string_result.txt', txHash) } } run() ``` -------------------------------- ### Deploying CKB Script to Devnet (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/simple-lock.mdx Deploys the compiled CKB script binary to the local Devnet using the `offckb` tool. The `-t` flag likely indicates a test deployment, and `--network devnet` specifies the target network. ```bash cd frontend && offckb deploy -t --network devnet ``` ```text contract HASH-LOCK deployed, tx hash: 0x9f55da2b555cdc4412945ff8827b7e77508c84f0b85d82b027d31418e6a9b5d9 wait 4 blocks.. done. ``` -------------------------------- ### Creating HTLC-Locked Cell on CKB (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This script is intended to create a cell on the CKB blockchain that is locked by the previously deployed HTLC script. It reads the Duktape binary to calculate its hash, takes the deployment transaction hash, private key, node URL, and two lock hashes (A and B) as input. The provided snippet initializes the CKB SDK and loads the secp256k1 dependency, but the transaction construction and sending logic is incomplete. ```JavaScript #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const crc32 = require('crc32') const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 8) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const duktapeBinary = fs.readFileSync(process.argv[2]) const duktapeHash = blake2b(duktapeBinary) const deployedTxHash = process.argv[3] const privateKey = process.argv[4] const nodeUrl = process.argv[5] const lockHashA = process.argv[6] const lockHashB = process.argv[7] function hexStringToHexStringArray(s) { let arr = [] for (let i = 2; i < s.length; i += 2) { arr.push('0x' + s.substr(i, 2)) } return arr } const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() ``` -------------------------------- ### Create Transaction to Deploy Script Data (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Demonstrates creating a transaction skeleton using Lumos to deploy a compiled script (`carrot`) as the data part of a new cell. It reads the script file, transfers capacity to a recipient address, updates the output cell's data with the script's hexadecimal representation, pays the fee, prepares signing entries, signs the transaction, and sends it to the CKB network. ```js > const fs = require("fs"); > const data = fs.readFileSync("carrot"); > data.byteLength 7744 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address], wallet2.address, "8000" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address], 1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const carrotTxHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### Illustrating Pipe Creation and Reading (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Illustrates the creation of pipes for inter-process communication and how the parent process reads data from one of the pipes. Two pipes are created to allow data flow in both directions between the caller and callee scripts. ```Rust let (r1, w1) = ckb_std::syscalls::pipe()?; let (r2, w2) = ckb_std::syscalls::pipe()?; let to_parent_fds: [u64; 2] = [r1, w2]; let to_child_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 // ... let len = ckb_std::syscalls::read(to_parent_fds[0], &mut buf)?; ``` -------------------------------- ### Build CKB Contracts using Make Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Executes the `make build` command to compile the CKB contracts defined in the project. ```Shell make build ``` -------------------------------- ### Lumos Utility Functions for Omnilock-Metamask (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/omnilock.mdx This TypeScript code defines essential functions for the Omnilock-Metamask example using the Lumos library. It includes type definitions for the Ethereum provider, an asynchronous sleep function, a function to transfer CKB, and a function to check the capacity (balance) of an address. It relies on Lumos for blockchain interactions and assumes integration with a MetaMask-like Ethereum provider for signing. ```TypeScript import { BI, Cell, helpers, Indexer, RPC, config, commons, } from "@ckb-lumos/lumos"; import { blockchain, bytify, hexify } from "@ckb-lumos/lumos/codec"; const CKB_RPC_URL = "https://testnet.ckb.dev/rpc"; const rpc = new RPC(CKB_RPC_URL); const indexer = new Indexer(CKB_RPC_URL); // prettier-ignore interface EthereumRpc { (payload: { method: 'personal_sign'; params: [string /*from*/, string /*message*/] }): Promise; } // prettier-ignore export interface EthereumProvider { selectedAddress: string; isMetaMask?: boolean; enable: () => Promise; addListener: (event: 'accountsChanged', listener: (addresses: string[]) => void) => void; removeEventListener: (event: 'accountsChanged', listener: (addresses: string[]) => void) => void; request: EthereumRpc; } // @ts-ignore export const ethereum = window.ethereum as EthereumProvider; export function asyncSleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } interface Options { from: string; to: string; amount: string; } const SECP_SIGNATURE_PLACEHOLDER = hexify( new Uint8Array( commons.omnilock.OmnilockWitnessLock.pack({ signature: new Uint8Array(65).buffer, }).byteLength ) ); export async function transfer(options: Options): Promise { const CONFIG = config.getConfig(); let tx = helpers.TransactionSkeleton({}); const fromScript = helpers.parseAddress(options.from); const toScript = helpers.parseAddress(options.to); // additional 0.001 ckb as tx fee // tx fee is calculated by tx size // this is just a simple example const neededCapacity = BI.from(options.amount).add(100000); let collectedSum = BI.from(0); const collectedCells: Cell[] = []; const collector = indexer.collector({ lock: fromScript, type: "empty" }); for await (const cell of collector.collect()) { collectedSum = collectedSum.add(cell.cellOutput.capacity); collectedCells.push(cell); if (BI.from(collectedSum).gte(neededCapacity)) break; } if (collectedSum.lt(neededCapacity)) { throw new Error( `Not enough CKB, expected: ${neededCapacity}, actual: ${collectedSum} ` ); } const transferOutput: Cell = { cellOutput: { capacity: BI.from(options.amount).toHexString(), lock: toScript, }, data: "0x", }; const changeOutput: Cell = { cellOutput: { capacity: collectedSum.sub(neededCapacity).toHexString(), lock: fromScript, }, data: "0x", }; tx = tx.update("inputs", (inputs) => inputs.push(...collectedCells)); tx = tx.update("outputs", (outputs) => outputs.push(transferOutput, changeOutput) ); tx = tx.update("cellDeps", (cellDeps) => cellDeps.push( // omni lock dep { outPoint: { txHash: CONFIG.SCRIPTS.OMNILOCK.TX_HASH, index: CONFIG.SCRIPTS.OMNILOCK.INDEX, }, depType: CONFIG.SCRIPTS.OMNILOCK.DEP_TYPE, }, // SECP256K1 lock is depended by omni lock { outPoint: { txHash: CONFIG.SCRIPTS.SECP256K1_BLAKE160.TX_HASH, index: CONFIG.SCRIPTS.SECP256K1_BLAKE160.INDEX, }, depType: CONFIG.SCRIPTS.SECP256K1_BLAKE160.DEP_TYPE, } ) ); const witness = hexify( blockchain.WitnessArgs.pack({ lock: SECP_SIGNATURE_PLACEHOLDER }) ); // fill txSkeleton's witness with placeholder for (let i = 0; i < tx.inputs.toArray().length; i++) { tx = tx.update("witnesses", (witnesses) => witnesses.push(witness)); } tx = commons.omnilock.prepareSigningEntries(tx, { config: CONFIG }); let signedMessage = await ethereum.request({ method: "personal_sign", params: [ethereum.selectedAddress, tx.signingEntries.get(0).message], }); let v = Number.parseInt(signedMessage.slice(-2), 16); if (v >= 27) v -= 27; signedMessage = "0x" + signedMessage.slice(2, -2) + v.toString(16).padStart(2, "0"); const signedWitness = hexify( blockchain.WitnessArgs.pack({ lock: commons.omnilock.OmnilockWitnessLock.pack({ signature: bytify(signedMessage).buffer, }), }) ); tx = tx.update("witnesses", (witnesses) => witnesses.set(0, signedWitness)); const signedTx = helpers.createTransactionFromSkeleton(tx); const txHash = await rpc.sendTransaction(signedTx, "passthrough"); return txHash; } export async function capacityOf(address: string): Promise { const collector = indexer.collector({ lock: helpers.parseAddress(address), }); let balance = BI.from(0); for await (const cell of collector.collect()) { balance = balance.add(cell.cellOutput.capacity); } return balance; } ``` -------------------------------- ### Creating HTLC Locked Cell on CKB using Node.js Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This Node.js script is designed to create a new cell on the CKB chain locked by a previously deployed HTLC script. It takes the deployed transaction hash, private key, node URL, and two lock hashes (A and B) as input, calculates the hash of the Duktape binary, loads necessary dependencies, and prepares to construct a transaction to create the HTLC-locked cell. ```JavaScript #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const crc32 = require('crc32') const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 8) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const duktapeBinary = fs.readFileSync(process.argv[2]) const duktapeHash = blake2b(duktapeBinary) const deployedTxHash = process.argv[3] const privateKey = process.argv[4] const nodeUrl = process.argv[5] const lockHashA = process.argv[6] const lockHashB = process.argv[7] function hexStringToHexStringArray(s) { let arr = [] for (let i = 2; i < s.length; i += 2) { arr.push('0x' + s.substr(i, 2)) } return arr } const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() ``` -------------------------------- ### Build and Send CKB Transaction with OffCKB REPL (javascript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Demonstrates building a CKB transaction in the `OffCKB` REPL environment. It constructs the script args, creates the `type` script, defines the transaction structure with outputs and cell dependencies, completes inputs and fee, signs, and sends the transaction. ```javascript let baseScriptArgs = `0x0000${myScripts['fib.bc'].codeHash.slice(2)}0${ccc.hashTypeToBytes(myScripts['fib.bc'].hashType).toString()}`; let baseScript = ccc.Script.from({ codeHash: myScripts["ckb-js-vm"].codeHash, hashType: myScripts["ckb-js-vm"].hashType, args: baseScriptArgs, }) let tx = ccc.Transaction.from({ outputs: [ { lock: accounts[0].lockScript, type: baseScript }, ], cellDeps: [ ...myScripts["ckb-js-vm"].cellDeps.map(c => c.cellDep), ...myScripts['fib.bc'].cellDeps.map(c => c.cellDep) ], }); let signer = new ccc.SignerCkbPrivateKey(client, accounts[0].privkey); await tx.completeInputsByCapacity(signer); await tx.completeFeeBy(signer, 1000); await signer.sendTransaction(tx); ``` -------------------------------- ### Constructing and Sending Transaction in OffCKB REPL Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx A sequence of commands executed within the offckb REPL to construct a CKB transaction, set output capacity and lock script, add cell dependencies from deployed scripts, complete inputs and fee using a signer, and finally send the transaction. ```OffCKB REPL (JS/CKB SDK) OffCKB > let amountInCKB = ccc.fixedPointFrom(63); OffCKB > let caller = myScripts['caller']; OffCKB > let lockScript = new ccc.Script(caller.codeHash, caller.hashType, "0x00"); OffCKB > let tx = ccc.Transaction.from({ ... outputs: [ ... { ... capacity: ccc.fixedPointFrom(amountInCKB), ... lock: lockScript, ... }, ... ], ... cellDeps: [ ... ...myScripts["callee"].cellDeps.map(c => c.cellDep), ... ...myScripts['caller'].cellDeps.map(c => c.cellDep), ... ]} ... ); OffCKB > let signer = new ccc.SignerCkbPrivateKey(client, accounts[0].privkey); OffCKB > await tx.completeInputsByCapacity(signer); 1 OffCKB > await tx.completeFeeBy(signer, 1000); [ 0, true ] OffCKB > await signer.sendTransaction(tx) '0x252305141e6b7db81f7da94b098493a36b756fe9d5d4436c9d7c966882bc0b38' ``` -------------------------------- ### Deploying Smart Contracts to Testnet with offckb (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-lock/README.md Navigates into the frontend project directory and executes the `offckb deploy` command specifically targeting the CKB Testnet. ```sh cd frontend offckb deploy --network testnet ``` -------------------------------- ### Unlocking HTLC Cell via Secret String (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md This script outlines the process for unlocking an HTLC-protected cell on the CKB network using a secret string. It parses command-line arguments for transaction hashes, private key, node URL, and the secret. It calculates the lock hash, loads user cells, and begins constructing the unlock transaction, including the serialization of the HTLC witness data using a Molecule schema. ```JavaScript $ cd $TOP/htlc-runner $ cat unlock_via_secret_string.js #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const crc32 = require('crc32') const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 8) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const deployedTxHash = process.argv[2] const htlcCellTxHash = process.argv[3] const privateKey = process.argv[4] const nodeUrl = process.argv[5] const secretString = process.argv[6] const dryrun = process.argv[7] === 'true' function stringToHexStringArray(s) { let a = [] for (let i = 0; i < s.length; i++) { a.push('0x' + ('00' + s.charCodeAt(i).toString(16)).slice(-2)) } return a } const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const htlcCellCapacity = 200000000000n const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcWitnessType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcWitness")) const htlcWitness = htlcWitnessType.serialize([ ``` -------------------------------- ### Serializing HTLC Arguments with Molecule (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This snippet demonstrates how to use the Molecule library to serialize the arguments for an HTLC script. It reads a custom Molecule schema from a JSON file, finds the definition for "HtlcArgs", and then serializes an array of key-value pairs representing the HTLC arguments (lock hashes 'a' and 'b', and the hash of the secret) into a byte string format suitable for use in a CKB script's `args` field. ```JavaScript const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcArgsType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcArgs")) const htlcScriptArgs = htlcArgsType.serialize([ ['a', hexStringToHexStringArray(lockHashA)], ['b', hexStringToHexStringArray(lockHashB)], ['hash', hexStringToHexStringArray('0x' + crc32('i am a secret'))] ]) ``` -------------------------------- ### Creating HTLC Cell Transaction (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This snippet demonstrates the process of constructing and sending a transaction to create an HTLC (Hashed Timelock Contract) cell on the CKB network. It involves deriving the lock hash from a private key, loading available cells, calculating capacities and fees, serializing HTLC arguments using Molecule, building the transaction structure with cell dependencies, inputs, outputs (including the HTLC cell and change cell), and witnesses, signing the transaction, and finally sending it to the CKB node. ```JavaScript const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const htlcCellCapacity = 200000000000n const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcArgsType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcArgs")) const htlcScriptArgs = htlcArgsType.serialize([ ['a', hexStringToHexStringArray(lockHashA)], ['b', hexStringToHexStringArray(lockHashB)], ['hash', hexStringToHexStringArray('0x' + crc32('i am a secret'))] ]) const transaction = { version: '0x0', cellDeps: [ { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs: [ { lock: { codeHash: utils.bytesToHex(duktapeHash), hashType: 'data', args: htlcScriptArgs }, type: null, capacity: '0x' + htlcCellCapacity.toString(16) }, { lock: lockScript, type: null, capacity: '0x' + (totalCapacity - fee - htlcCellCapacity).toString(16) } ], witnesses: [ { lock: '', inputType: '', outputType: '' } ], outputsData: [ '0x', '0x' ] } const signedTransaction = ckb.signTransaction(privateKey)(transaction) const txHash = await ckb.rpc.sendTransaction(signedTransaction, 'passthrough') console.log(`Transaction hash: ${txHash}`) fs.writeFileSync('create_htlc_cell_result.txt', txHash) } run() ``` -------------------------------- ### Configuring Frontend Network Target in .env (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-lock/README.md Shows how to modify the `.env` file in the frontend project to set the `NEXT_PUBLIC_NETWORK` environment variable, controlling which CKB network (devnet, testnet, or mainnet) the frontend Dapp will connect to. ```bash NEXT_PUBLIC_NETWORK=testnet # devnet, testnet or mainnet ``` -------------------------------- ### Listing Pre-funded Devnet Accounts (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/_StartDevnet.mdx This command lists the pre-funded accounts available in the Devnet genesis block. Each account is funded with a large capacity and includes the private key, public key, lock script details, and address. This is useful for obtaining private keys for testing. The output displays a JSON array of account objects. ```bash offckb accounts ``` -------------------------------- ### Test HTLC Unlock via Timeout (Insufficient Time) - CKB Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Runs the `unlock_via_timeout.js` script with a block hash corresponding to a block number (409) that is before the required timeout period, showing the expected validation failure. This test confirms that the timeout period must be reached for this unlocking method to succeed. ```Shell $ ./unlock_via_timeout.js \\ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \\ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \\ 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d \\ "http://127.0.0.1:8114/" \\ 0xe93ebb311d156847fbcdc159d1fa3c38f12613121e51582272d909379c4d1a60 \\ true ``` -------------------------------- ### Initialize CKB Node for Mainnet - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-mainnet-node.mdx Initializes the CKB node configuration files specifically for connecting to the mainnet. This command sets up the necessary directories and default configuration. ```bash ckb init --chain mainnet ``` -------------------------------- ### Unlocking HTLC Cell Transaction (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This script demonstrates how to construct a transaction to unlock an HTLC (Hashed Timelock Contract) cell on the CKB network by providing the secret string. It parses command-line arguments for transaction hashes, private key, node URL, secret, and dry run flag. It sets up the CKB connection, loads dependencies, derives the lock hash, loads user cells, and prepares for Molecule serialization of the HTLC witness data, including the secret. ```JavaScript #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const crc32 = require('crc32') const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 8) { console.log(`Usage: ${process.argv[1]} `) process.exit(1) } const deployedTxHash = process.argv[2] const htlcCellTxHash = process.argv[3] const privateKey = process.argv[4] const nodeUrl = process.argv[5] const secretString = process.argv[6] const dryrun = process.argv[7] === 'true' function stringToHexStringArray(s) { let a = [] for (let i = 0; i < s.length; i++) { a.push('0x' + ('00' + s.charCodeAt(i).toString(16)).slice(-2)) } return a } const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const htlcCellCapacity = 200000000000n const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcWitnessType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcWitness")) const htlcWitness = htlcWitnessType.serialize([ ``` -------------------------------- ### Building the Java Project with Gradle Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/java.mdx Command to build the Java project using Gradle, resolving dependencies and compiling source code. ```Bash gradle build ``` -------------------------------- ### Constructing CKB Transaction for HTLC Timeout Unlock (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This JavaScript code snippet prepares a CKB transaction to unlock an HTLC cell after the timeout period has passed. It initializes the CKB SDK, loads dependencies, retrieves necessary transaction/block information, constructs the transaction including header dependencies to prove time passage, and serializes the HTLC witness data indicating timeout using Molecule. ```JavaScript $ cd $TOP/htlc-runner $ cat unlock_via_timeout.js #!/usr/bin/env node const { Molecule } = require('molecule-javascript') const crc32 = require('crc32') const CKB = require("@nervosnetwork/ckb-sdk-core").default const utils = require("@nervosnetwork/ckb-sdk-utils") const process = require('process') const fs = require('fs') function blake2b(buffer) { return utils.blake2b(32, null, null, utils.PERSONAL).update(buffer).digest('binary') } if (process.argv.length !== 8) { console.log(`Usage: ${process.argv[1]}
`) process.exit(1) } const deployedTxHash = process.argv[2] const htlcCellTxHash = process.argv[3] const privateKey = process.argv[4] const nodeUrl = process.argv[5] const headerHash = process.argv[6] const dryrun = process.argv[7] === 'true' const run = async () => { const ckb = new CKB(nodeUrl) const secp256k1Dep = await ckb.loadSecp256k1Dep() const htlcCellTx = await ckb.rpc.getTransaction(htlcCellTxHash) const htlcCellHeaderHash = htlcCellTx.txStatus.blockHash const publicKey = ckb.utils.privateKeyToPublicKey(privateKey) const publicKeyHash = `0x${ckb.utils.blake160(publicKey, 'hex')}` const lockScript = { hashType: secp256k1Dep.hashType, codeHash: secp256k1Dep.codeHash, args: publicKeyHash } const lockHash = ckb.utils.scriptToHash(lockScript) const unspentCells = await ckb.loadCells({ lockHash }) const totalCapacity = unspentCells.reduce((sum, cell) => sum + BigInt(cell.capacity), 0n) // For simplicity, we will just use 1 CKB as fee. On a real setup you // might not want to do this. const fee = 100000000n const htlcCellCapacity = 200000000000n const customSchema = JSON.parse(fs.readFileSync('../htlc-template/src/htlc-combined.json')) const htlcWitnessType = new Molecule( customSchema.declarations.find(d => d.name == "HtlcWitness")) const htlcWitness = htlcWitnessType.serialize([ ['s', []], ['i', ['0x1', '0x0', '0x0', '0x0']] ]) const transaction = { version: '0x0', cellDeps: [ // Due to the requirement of load0 duktape binary, JavaScript source cell // should be the first one in cell deps { outPoint: { txHash: deployedTxHash, index: "0x1" }, depType: 'code' }, { outPoint: { txHash: deployedTxHash, index: "0x0" }, depType: 'code' }, { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' } ], headerDeps: [ htlcCellHeaderHash, headerHash, ], inputs: unspentCells.map(cell => ({ previousOutput: cell.outPoint, since: '0x0' })), outputs: [ { lock: lockScript, type: null, capacity: '0x' + (totalCapacity + htlcCellCapacity - fee).toString(16) } ], witnesses: unspentCells.map(_cell => '0x'), outputsData: [ '0x', '0x' ] } ``` -------------------------------- ### Implement Carrot Forbidden Logic with CKB-STD Rust Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx This Rust code implements the core logic for the "carrot-forbidden" CKB script. It iterates through the data of output cells using `ckb_std::high_level::load_cell_data` and checks if any cell data starts with the bytes representing "carrot". If found, it returns a specific error code; otherwise, it returns success after checking all relevant output cells. ```Rust #![no_std] #![cfg_attr(not(test), no_main)] #[cfg(test)] extern crate alloc; mod error; use ckb_std::{ckb_constants::Source, debug, error::SysError, high_level::load_cell_data}; #[cfg(not(test))] use ckb_std::default_alloc; use error::Error; #[cfg(not(test))] ckb_std::entry!(program_entry); #[cfg(not(test))] default_alloc!(); pub fn program_entry() -> i8 { match carrot_forbidden() { Ok(_) => 0, Err(err) => err as i8, } } fn carrot_forbidden() -> Result<(), Error> { let mut index = 0; loop { match load_cell_data(index, Source::GroupOutput) { Ok(data) => { if data.starts_with("carrot".as_bytes()) { return Err(Error::CarrotAttack); }else{ debug!("output #{:} has no carrot! Hooray!", index); } }, Err(err) => { match err { // we loop out all the output cell SysError::IndexOutOfBound => break, _ => return Err(Error::from(err)), } } } // Increment index to process next cell index += 1; } Ok(()) } ``` -------------------------------- ### Test HTLC Unlock via Timeout (Wrong Public Key) - CKB Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Executes the `unlock_via_timeout.js` script with sufficient time but an incorrect public key, demonstrating that validation still fails if the public key doesn't match the cell's lock script, even when the timeout is met. This confirms the public key requirement for timeout unlocking. ```Shell $ ./unlock_via_timeout.js \\ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \\ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \\ 0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc \\ "http://127.0.0.1:8114/" \\ 0x665ccfab2d854afa035f4697a2301f2bad9d4aa86506090b104f8ed18772ca01 \\ true ``` -------------------------------- ### Test HTLC Unlock via Secret (Invalid Public Key) - CKB Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-7.md Runs the `unlock_via_secret_string.js` script with a correct secret but an incorrect public key to show that validation still fails if the public key doesn't match the cell's lock script. This confirms that both the correct secret and the correct public key are required for this unlocking method. ```Shell $ ./unlock_via_secret_string.js \\ 0xf30e1e8989fc3a4cb1e52dacc85090f8ff74b05e008d636b8c9154f5c296e1f4 \\ 0x7de8ea6b0d6cb9941e76976d1d55edf844c4fa81485e00fb8eba2d161b5830cd \\ 0x63d86723e08f0f813a36ce6aa123bb2289d90680ae1e99d4de8cdb334553f24d \\ "http://127.0.0.1:8114/" \\ "i am a secret" \\ true ``` -------------------------------- ### Defining HTLC Data Structures with Molecule Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-7.md This snippet shows the definition of `HtlcArgs` and `HtlcWitness` data structures using the Molecule serialization format. These structures are intended to hold custom arguments for an HTLC script, used in the `args` and `witnesses` fields of a CKB transaction. `HtlcArgs` contains two 32-byte fields and a 32-bit integer for public keys and hash, while `HtlcWitness` is a table containing optional fields for a secret string or a block header index. ```Shell cd $TOP/htlc-template cat htlc.mol ``` ```Molecule array Uint32 [byte; 4]; array Byte32 [byte; 32]; vector Bytes ; struct HtlcArgs { a: Byte32, b: Byte32, hash: Uint32, } table HtlcWitness { s: Bytes, i: Uint32, } ``` -------------------------------- ### Cloning and Checking Out Benchmark Scripts Repository Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Navigates to the project root, clones the ckb-vm-bench-scripts repository recursively, enters the cloned directory, checks out a specific commit hash (f7ab37c055b1a59bbc4f931c732331642c728c1d), and then returns to the project root. ```Shell cd $TOP git clone --recursive https://github.com/nervosnetwork/ckb-vm-bench-scripts cd ckb-vm-bench-scripts git checkout f7ab37c055b1a59bbc4f931c732331642c728c1d cd $TOP ``` -------------------------------- ### Get Transaction Status via Curl Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/rpcs.mdx This command uses curl to send a JSON RPC request to the CKB node's HTTP endpoint (http://localhost:8114) to fetch the status of a transaction (get_transaction). It pipes a JSON payload containing the RPC method and parameters (the transaction hash) via echo, removes newlines with tr -d '\n', and sends it as the request body with the correct content type. ```bash echo '{ "id": 4, "jsonrpc": "2.0", "method": "get_transaction", "params": ["0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3"] }' \ | tr -d '\n' \ | curl -H 'content-type: application/json' -d @- \ http://localhost:8114 ``` -------------------------------- ### Deploy Script Binary as Cell Data using Lumos Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This JavaScript code demonstrates how to deploy the compiled script binary (`carrot`) to the CKB blockchain. It reads the binary file, creates a transaction skeleton, transfers capacity to a new cell, updates the output cell to include the script binary as its data, pays the transaction fee, prepares signing entries, signs the transaction with the wallet's private key, and sends it to the network. ```js > const fs = require("fs"); > const data = fs.readFileSync("carrot"); > data.byteLength 7744 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address], wallet2.address, "8000" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address], 1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const carrotTxHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### React Component for Issuing xUDT with SUS Lock Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/ccc.mdx This React component provides a user interface and logic for issuing xUDT tokens. It guides the user through the process which involves creating a Single-Use Lock cell, an owner cell locked by the SUS, and finally the transaction that mints the xUDT and creates the xUDT info cell, consuming the SUS and owner cells. It utilizes the @ckb-ccc/connector-react library for interacting with the CKB network. ```tsx "use client";\n\nimport { useState } from "react";\nimport { TextInput } from "@/src/components/Input";\nimport { Button } from "@/src/components/Button";\nimport { ccc } from "@ckb-ccc/connector-react";\nimport { tokenInfoToBytes, useGetExplorerLink } from "@/src/utils";\nimport { Message } from "@/src/components/Message";\nimport React from "react";\nimport { useApp } from "@/src/context";\nimport { ButtonsPanel } from "@/src/components/ButtonsPanel";\nimport Link from "next/link";\n\nexport default function IssueXUdtSul() {\n const { signer, createSender } = useApp();\n const { log, error } = createSender("Issue xUDT (SUS)");\n\n const { explorerTransaction } = useGetExplorerLink();\n\n const [amount, setAmount] = useState("");\n const [decimals, setDecimals] = useState("");\n const [name, setName] = useState("");\n const [symbol, setSymbol] = useState("");\n\n return (\n <>\n
\n \n You will need to sign two or three transactions.\n
\n Learn more on{" "}\n \n [EN/CN] Misc: Single-Use-Seals - 杂谈:一次性密封\n \n
\n\n \n \n \n \n\n \n {\n if (!signer) {\n return;\n }\n if (decimals === "" || symbol === "") {\n error("Invalid token info");\n return;\n }\n\n const { script } = await signer.getRecommendedAddressObj();\n\n const susTx = ccc.Transaction.from({\n outputs: [\n {\n lock: script,\n },\n ],\n });\n await susTx.completeInputsByCapacity(signer);\n await susTx.completeFeeBy(signer);\n const susTxHash = await signer.sendTransaction(susTx);\n log("Transaction sent:", explorerTransaction(susTxHash));\n await signer.client.cache.markUnusable({\n txHash: susTxHash,\n index: 0,\n });\n\n const singleUseLock = await ccc.Script.fromKnownScript(\n signer.client,\n ccc.KnownScript.SingleUseLock,\n ccc.OutPoint.from({\n txHash: susTxHash,\n index: 0,\n }).toBytes()\n );\n const lockTx = ccc.Transaction.from({\n outputs: [\n // Owner cell\n {\n lock: singleUseLock,\n },\n ],\n });\n await lockTx.completeInputsByCapacity(signer);\n await lockTx.completeFeeBy(signer);\n const lockTxHash = await signer.sendTransaction(lockTx);\n log("Transaction sent:", explorerTransaction(lockTxHash));\n\n const mintTx = ccc.Transaction.from({\n inputs: [\n // SUS\n {\n previousOutput: {\n txHash: susTxHash,\n index: 0,\n },\n },\n // Owner cell\n {\n previousOutput: {\n txHash: lockTxHash,\n index: 0,\n },\n },\n ],\n outputs: [\n // Issued xUDT\n {\n lock: script,\n type: await ccc.Script.fromKnownScript(\n signer.client,\n ccc.KnownScript.XUdt,\n singleUseLock.hash()\n ),\n },\n // xUDT Info\n {\n lock: script,\n type: await ccc.Script.fromKnownScript(\n signer.client,\n ccc.KnownScript.UniqueType,\n "00".repeat(32)\n ),\n },\n ], ``` -------------------------------- ### Generating New CKB Script 'caller' with make (Response) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx This output confirms the successful generation of the `caller` script module. It shows the destination path, template processing, and file creation within the `contracts/caller` subdirectory of the main project. ```bash 🤷 Project Name: caller 🔧 Destination: /tmp/spawn-script/contracts/caller ... 🔧 project-name: caller ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/spawn-script/contracts/caller`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/caller-script/contracts/caller ``` -------------------------------- ### Deploying Duktape Binary on CKB using Lumos Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-3.md JavaScript code using the Lumos library to read the Duktape binary file, create a transaction to deploy it as a cell on CKB, sign the transaction, and send it to the RPC node. This makes the Duktape VM available as a script. ```javascript const fs = require("fs"); const data = fs.readFileSync("../ckb-duktape/build/duktape"); data.byteLength; let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); txSkeleton = await lumos.commons.common.transfer(txSkeleton, [wallet.address], wallet2.address, "292000" + "00000000"); txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton, [wallet.address], 1000); txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures); const duktapeTxHash = await rpc.sendTransaction(signedTx); const duktapeCodeHash = lumos.utils.ckbHash(bytes.bytify("0x" + data.toString("hex"))); ``` -------------------------------- ### Prepare Transaction for Signing using Lumos Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This JavaScript snippet prepares the transaction skeleton for signing. It calculates the transaction fee using `payFeeByFeeRate` and then generates the signing entries required for creating signatures. ```js > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); ``` -------------------------------- ### Creating WAVM C Main File (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Creates the `secp_wavm_main.c` file using a `cat << EOF` block. This C file includes WAVM-specific headers (`secp_precompiled_glue.h`, `abi/ckb_vm_wasi_abi.h`) and `ckb_syscalls.h`. The `main` function loads a value, loops, and calls the WAVM exported function `wavm_exported_function_run`, accumulating the result. ```Shell $ cat << EOF > secp_wavm_main.c #include "secp_precompiled_glue.h" #include "abi/ckb_vm_wasi_abi.h" #include "ckb_syscalls.h" int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } uint32_t times = value >> 8; value = value & 0xFF; uint8_t result = 0; for (int i = 0; i < times; i++) { ckb_debug("One run!"); wavm_ret_int32_t wavm_ret = wavm_exported_function_run(NULL, value); result += wavm_ret.value; } return result; } EOF ``` -------------------------------- ### Build and Run RISC-V binary with CKB VM Test Suite (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-4.md Commands to clone the necessary repositories (ckb-vm-test-suite, ckb-vm), build the test suite's binary executable, and then use this binary (asm64) to run the previously compiled fib_riscv64 program with different input values (5 and 10), showing the output. ```Shell $ git clone --recursive https://github.com/nervosnetwork/ckb-vm-test-suite $ cd ckb-vm-test-suite $ git clone https://github.com/nervosnetwork/ckb-vm $ cd binary $ cargo build --release $ cd ../.. $ ckb-vm-test-suite/binary/target/release/asm64 fib_riscv64 5 Error result: Ok(8) $ ckb-vm-test-suite/binary/target/release/asm64 fib_riscv64 10 Error result: Ok(89) ``` -------------------------------- ### Including Error Module and Libraries (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Includes the custom error module and necessary libraries from `ckb_std` and `core::ffi` required for using syscalls like `Spawn` and handling C-style strings. ```Rust mod error; use ckb_std::syscalls::SpawnArgs; use core::ffi::CStr; ``` -------------------------------- ### Deploying Duktape to CKB using Lumos (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-3.md This JavaScript snippet demonstrates how to deploy the Duktape executable to CKB as a cell using the Lumos library. It reads the Duktape binary from the filesystem, creates a transaction skeleton, adds the binary data to an output cell, signs the transaction, and sends it to the CKB node. ```javascript > const fs = require("fs"); > const data = fs.readFileSync("../ckb-duktape/build/duktape"); > data.byteLength 291440 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton, [wallet.address], wallet2.address, "292000" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton, [wallet.address], 1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const duktapeTxHash = await rpc.sendTransaction(signedTx) > const duktapeCodeHash = lumos.utils.ckbHash(bytes.bytify("0x" + data.toString("hex"))); ``` -------------------------------- ### Write CKB Contract Unit Test in Rust Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Demonstrates how to write a unit test for CKB contracts using `ckb-testtool`. It deploys caller and callee contracts, prepares transaction inputs/outputs, defines cell dependencies, builds and completes a transaction, and verifies its execution using `context.verify_tx`. ```Rust use crate::Loader; use ckb_testtool::ckb_types::{ bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*, }; use ckb_testtool::context::Context; // Include your tests here // See https://github.com/xxuejie/ckb-native-build-sample/blob/main/tests/src/tests.rs for more examples // generated unit test for contract caller #[test] fn test_spawn() { // deploy contract let mut context = Context::default(); let caller_contract_bin: Bytes = Loader::default().load_binary("caller"); let caller_out_point = context.deploy_cell(caller_contract_bin); let callee_contract_bin: Bytes = Loader::default().load_binary("callee"); let callee_out_point = context.deploy_cell(callee_contract_bin); // prepare scripts let lock_script = context .build_script(&caller_out_point, Bytes::from(vec![42])) .expect("script"); // prepare cells let input_out_point = context.create_cell( CellOutput::new_builder() .capacity(1000u64.pack()) .lock(lock_script.clone()) .build(), Bytes::new(), ); let input = CellInput::new_builder() .previous_output(input_out_point) .build(); let outputs = vec![ CellOutput::new_builder() .capacity(500u64.pack()) .lock(lock_script.clone()) .build(), CellOutput::new_builder() .capacity(500u64.pack()) .lock(lock_script) .build(), ]; let outputs_data = vec![Bytes::new(); 2]; // prepare cell deps let callee_dep = CellDep::new_builder() .out_point(callee_out_point) .build(); let caller_dep = CellDep::new_builder() .out_point(caller_out_point) .build(); let cell_deps: Vec = vec![callee_dep, caller_dep]; // build transaction let tx = TransactionBuilder::default() .input(input) .outputs(outputs) .outputs_data(outputs_data.pack()) .cell_deps(cell_deps) .build(); let tx = context.complete_tx(tx); // run let cycles = context .verify_tx(&tx, 10_000_000) .expect("pass verification"); println!("consume cycles: {}", cycles); } ``` -------------------------------- ### Prepare CKB Transaction for Duktape Deployment (Lumos) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Demonstrates how to use Node.js and the Lumos library to read the compiled Duktape binary file and initialize a transaction skeleton for deploying the binary onto the CKB blockchain, including adding transfer details. ```JavaScript > const data = fs.readFileSync("../ckb-duktape/build/duktape"); > data.byteLength 291440 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"292000" + "00000000"); ``` -------------------------------- ### Signing and Sending CKB Transaction (Lumos JS) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Demonstrates the final steps of signing a prepared transaction skeleton using Lumos helper functions and sending it to the CKB network via RPC. Requires a `txSkeleton` with signing entries and a `wallet` with a private key. Outputs the transaction hash. ```JavaScript > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const txHash = await rpc.sendTransaction(signedTx) > txHash ``` -------------------------------- ### Navigate to CKB Directory (Windows) - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-mainnet-node.mdx Changes the current directory in the command prompt to the location where the CKB binary was unzipped on Windows. Assumes the binary was unzipped to `C:/`. ```bash cd C:/ckb_v0.115.0_x86_64-pc-windows-msvc ``` -------------------------------- ### Deploying ckb-duktape REPL Binary using Lumos Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md This JavaScript snippet, intended for a Node.js environment using the Lumos library, demonstrates how to read the compiled ckb-duktape REPL binary, create a CKB transaction to deploy it as cell data, sign the transaction, and send it to the CKB testnet. ```javascript $ node Welcome to Node.js v20.12.0. Type ".help" for more information. > > const lumos = require("@ckb-lumos/lumos"); > const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); > const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); > lumos.config.initializeConfig(lumos.config.TESTNET); > const wallet = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqvwg2cen8extgq8s5puft8vf40px3f599cytcyd8", privkey: "0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6", }; > const wallet2 = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2prryvze6fhufxkgjx35psh7w70k3hz7c3mtl4d", privkey: "0xace08599f3174f4376ae51fdc30950d4f2d731440382bb0aa1b6b0bd3a9728cd" } > const data = fs.readFileSync("./ckb-duktape/build/repl"); > data.byteLength 306040 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"306240" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const duktapeReplTxHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### Creating New Project with pnpm (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Uses the `create-ccc-app` CLI tool via pnpm to quickly scaffold a new project with built-in CCC wallet connection support. ```Bash pnpm create ccc-app ``` -------------------------------- ### Deploying Duktape Script on CKB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This JavaScript snippet demonstrates how to read the compiled Duktape RISC-V binary file from the filesystem, check its size, and prepare a CKB transaction using the Lumos library to transfer the binary data into a cell on the blockchain, making it available as a script code. ```javascript > const data = fs.readFileSync("../ckb-duktape/build/duktape"); > data.byteLength 291440 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"292000" + "00000000"); ``` -------------------------------- ### OffCKB Debug Output Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Output from the offckb debug command, showing that the transaction was dumped successfully and providing the run result and cycle consumption for the Input[0].Lock script. ```sh Dump transaction successfully ****************************** ****** Input[0].Lock ****** Run result: 0 All cycles: 1646754(1.6M) ``` -------------------------------- ### Convert WebAssembly to C Source Code Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-4.md Provides shell commands to clone the `wabt` repository (WebAssembly Binary Toolkit), build the project using cmake, and use the `wasm2c` tool from the built binaries to convert the `fib.wasm` file into C source code (`fib.c`). ```Shell $ git clone --recursive https://github.com/WebAssembly/wabt $ cd wabt $ mkdir build $ cd build $ cmake .. $ cmake --build . $ cd ../.. $ wabt/bin/wasm2c fib.wasm -o fib.c ``` -------------------------------- ### C Wrapper for WAVM (fib_wavm_main.c) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md C code providing a main function and necessary includes/definitions for running the WAVM precompiled code on CKB. It includes WAVM glue code, handles WASI aborts via `ckb_exit`, loads input from witness data, and calls the WAVM-exported `fib` function. ```C cd $TOP cat << EOF > fib_wavm_main.c #include "fib_precompiled_glue.h" #include "abi/ckb_vm_wasi_abi.h" #include "ckb_syscalls.h" void* wavm_env_abort(void* dummy, int32_t code, int32_t a, int32_t b, int32_t c) { ckb_exit(code); return dummy; } int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } wavm_ret_int32_t wavm_ret = wavm_exported_function_fib(NULL, value); return wavm_ret.value; } EOF ``` -------------------------------- ### Creating New Project with npx (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Uses the `create-ccc-app` CLI tool via npx to quickly scaffold a new project with built-in CCC wallet connection support. Using `@latest` ensures the most recent version is used. ```Bash npx create-ccc-app@latest ``` -------------------------------- ### Show Project Structure - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx Command to display the directory structure of the initialized CKB script workspace, highlighting the location of the new 'carrot' script source file. ```Bash tree . ``` -------------------------------- ### Create C Wrapper for WASM Function Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-4.md A simple C program (`main.c`) that includes the generated `fib.h`, reads an integer argument from the command line, initializes the WASM runtime (`init`), calls the converted fibonacci function (`Z_fibZ_ii`), and returns the result. ```C #include #include #include "fib.h" int main(int argc, char** argv) { if (argc < 2) return 2; u8 x = atoi(argv[1]); init(); u8 result = Z_fibZ_ii(x); return result; } ``` -------------------------------- ### Compile CKB Script with Docker RISC-V Toolchain Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This bash script demonstrates how to compile a CKB script written in C (`carrot.c`) using a pre-built Docker image containing the RISC-V GNU toolchain. It mounts the current directory into the container, navigates to it, compiles the code using `riscv64-unknown-elf-gcc`, and then exits the container. ```bash $ ls carrot.c ckb_consts.h ckb_syscalls.h $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash root@dc2c0c209dcd:/# cd /code root@dc2c0c209dcd:/code# riscv64-unknown-elf-gcc -Os carrot.c -o carrot root@dc2c0c209dcd:/code# exit exit $ ls carrot* carrot.c ckb_consts.h ckb_syscalls.h ``` -------------------------------- ### Simplified Generated IPC Client Implementation - Rust Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/ckb-script-ipc.mdx Shows a simplified version of the client-side code generated by the `#[ckb_script_ipc::service]` macro. It includes the implementation of a method (`hello`) that calls the corresponding service method over the IPC channel, handling requests and responses. ```rust impl WorldClient where R: ckb_script_ipc_common::io::Read, W: ckb_script_ipc_common::io::Write, { pub fn hello(&mut self, name: String) -> Result { let request = WorldRequest::Hello { name }; let resp: Result<_, ckb_script_ipc_common::error::IpcError> = self .channel .call::<_, WorldResponse>("World.hello", request); match resp { Ok(WorldResponse::Hello(ret)) => ret, Err(e) => { // Error handling code } } } } ``` -------------------------------- ### Deploying Smart Contracts to Devnet with offckb (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-lock/README.md Navigates into the frontend project directory and executes the `offckb deploy` command targeting the devnet. The `-t` flag is included, which might indicate a specific test or target configuration. ```sh cd frontend offckb deploy -t --network devnet ``` -------------------------------- ### Initialize CKB Script Project - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx Command to initialize a new CKB script workspace using `cargo generate` and the `ckb-script-templates`. It prompts the user for a project name. ```Bash alias create-ckb-scripts="cargo generate gh:cryptape/ckb-script-templates workspace" create-ckb-scripts ``` -------------------------------- ### Create C Source File (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Uses a here-document to write the C code for the CKB script into a file named c.c in the current directory. ```Shell cat << EOF > c.c #include "blockchain.h" #include "ckb_syscalls.h" #define MAXIMUM_ARG_SIZE 4096 #define SCRIPT_SIZE 32768 #define ERROR_ARGUMENTS_LEN -1 #define ERROR_ENCODING -2 #define ERROR_SYSCALL -3 #define ERROR_SCRIPT_TOO_LONG -21 #define ERROR_OVERFLOWING -51 #define ERROR_AMOUNT -52 int main() { unsigned char script[SCRIPT_SIZE]; uint64_t len = SCRIPT_SIZE; int ret = ckb_load_script(script, &len, 0); if (ret != CKB_SUCCESS) { return ERROR_SYSCALL; } if (len > SCRIPT_SIZE) { return ERROR_SCRIPT_TOO_LONG; } mol_seg_t script_seg; script_seg.ptr = (uint8_t *)script; script_seg.size = len; if (MolReader_Script_verify(&script_seg, false) != MOL_OK) { return ERROR_ENCODING; } mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); if (args_bytes_seg.size > MAXIMUM_ARG_SIZE) { return ERROR_ARGUMENTS_LEN; } static const char HEXCHARS[] = "0123456789abcdef"; char hex[MAXIMUM_ARG_SIZE * 2 + 1]; for (size_t i = 0; i < args_bytes_seg.size; i++) { hex[i * 2] = HEXCHARS[args_bytes_seg.ptr[i] >> 4]; hex[i * 2 + 1] = HEXCHARS[args_bytes_seg.ptr[i] & 0xF]; } hex[args_bytes_seg.size * 2] = '\0'; ckb_debug(hex); return CKB_SUCCESS; } EOF ``` -------------------------------- ### Compiling ckb-duktape REPL Binary Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md This snippet provides bash commands to clone the ckb-duktape repository, enter a Docker container with the necessary RISC-V toolchain, and compile the duktape and repl binaries required for the REPL workflow on CKB. ```bash $ git clone https://github.com/nervosnetwork/ckb-duktape $ cd ckb-duktape $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191012 bash root@982d1e906b76:/# cd /code root@982d1e906b76:/code# make riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror c/entry.c -c -o build/entry.o riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror duktape/duktape.c -c -o build/duktape.o riscv64-unknown-elf-gcc build/entry.o build/duktape.o -o build/duktape -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror c/repl.c -c -o build/repl.o riscv64-unknown-elf-gcc build/repl.o build/duktape.o -o build/repl -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s root@982d1e906b76:/code# exit ``` -------------------------------- ### Create Dependencies Directory (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Navigates into the newly created project directory and creates a subdirectory named 'deps' to store necessary dependencies like the ckb-js-vm binary and compile script. ```Shell cd ckb-js-script mkdir deps ``` -------------------------------- ### Creating Initial UDT Cell using Lumos Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-3.md JavaScript code using Lumos to create the first cell for the UDT, which will hold the initial token supply. It demonstrates how to build the transaction skeleton and extract the `outPointHex` needed as an argument for the UDT script during creation. ```javascript let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); txSkeleton = await lumos.commons.common.transfer(txSkeleton, [wallet.address], wallet2.address, "1820" + "00000000"); const blockchain = require("@ckb-lumos/base").blockchain; const outPointBuf = blockchain.OutPoint.pack(txSkeleton.get("inputs").first().outPoint); const outPointHex = Buffer.from(outPointBuf).toString("hex"); outPointHex; ``` -------------------------------- ### Creating WABT C Main File (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Creates the `secp_wabt_main.c` file using a `cat << EOF` block. This C file includes necessary headers (`ckb_syscalls.h`, `secp.h`) and contains the `main` function logic for the WABT version, which loads a value from a witness, initializes, and runs a loop calling `Z_runZ_ii`. ```Shell $ cd $TOP $ cat << EOF > secp_wabt_main.c #include #include #include "ckb_syscalls.h" #include "secp.h" int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } init(); uint32_t times = value >> 8; value = value & 0xFF; uint8_t result = 0; for (int i = 0; i < times; i++) { result += Z_runZ_ii(value); } return result; } EOF ``` -------------------------------- ### Change Directory to Project Root (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Changes the current directory to the project's top-level directory, typically stored in the $TOP environment variable, in preparation for creating the C source file. ```Shell cd $TOP ``` -------------------------------- ### Deploy Binary Script with OffCKB (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Deploys the compiled `fib.bc` binary script to the CKB chain using the `offckb deploy` command with the `--type-id` flag. ```sh offckb deploy --target ./js/build/fib.bc --type-id ``` -------------------------------- ### Generating New CKB Script 'callee' with make (Command) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx This command executes `make generate` again within the project root. It is used to create another new script module based on the template, this time named `callee`. ```bash make generate ``` -------------------------------- ### ZetZ Build Error with Insufficient Buffer Size Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-10.md Shows the output of the `zz build` command when the `load_data` function is called with a buffer smaller than required by its `where` clause. It illustrates how the SMT solver detects and reports the violation during the build process. ```Shell $ zz build [ERROR] unproven callsite assert for infix expression --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:15:25 | 15 | int ret = load_data(index, buffer);⌊ | ^------------^ | = in this callsite --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:5:22 | 5 | where len(buffer) >= 6 {⌊ | ^^ | = function call requires these conditions --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:4:1 | 4 | fn load_data(u64 index, u8 mut * buffer) -> int⌊ | ... 9 | }⌊ | ^ | = for this function --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:5:22 | 5 | where len(buffer) >= 6 {⌊ | ^^ | = for infix expression |0| = false --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:5:14 | 5 | where len(buffer) >= 6 {⌊ | ^-----^ | = for literal 3 |0| = 0x3 --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:5:25 | 5 | where len(buffer) >= 6 {⌊ | ^ | = for literal 6 |0| = 0x6 --> /home/ubuntu/code/ckb-zz-demo/src/main.zz:15:25 | 15 | int ret = load_data(index, buffer);⌊ | ^------------^ | = last callsite ``` -------------------------------- ### Creating New Project with Yarn (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Uses the `create-ccc-app` CLI tool via Yarn to quickly scaffold a new project with built-in CCC wallet connection support. ```Bash yarn create ccc-app ``` -------------------------------- ### Compiling WASM to Precompiled Format with WAVM Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Uses the WAVM compiler to take a release build of the wasm-secp256k1-test WASM module and compile it into a WAVM-specific precompiled format targeting riscv64. ```Shell WAVM/build/bin/wavm compile --target-triple riscv64 wasm-secp256k1-test/target/wasm32-unknown-unknown/release/wasm-secp256k1-test.wasm secp_precompiled.wasm ``` -------------------------------- ### Dump CKB VM State using Debugger (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Executes a script (`dump_load0`) that initializes a Duktape VM instance and calls a special debugger syscall to dump the VM's state into a binary file (`dump0.bin`). This command uses `ckb-standalone-debugger` to perform the execution and dumping. ```shell $ cd $TOP $ RUST_LOG=debug ./runner.rb ckb-duktape/build/dump_load0 ckb-duktape-template/build/duktape.js dump0.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input -d dump0.bin DEBUG:: script group: Byte32(0xb5656359cbcd52cfa68e163cdd217657f0cfc533c909d13a1fdd8032f6b4f1f0) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 20199104 Transfer cycles: 67352, running cycles: 20131752 ``` -------------------------------- ### Compiling JS to Duktape Bytecode and Running on CKB VM (dump_load0) - Shell Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md This snippet demonstrates compiling a JavaScript file (`duktape.js`) into Duktape bytecode (`script.bin`) using `dump_bytecode`, and then executing the bytecode on the CKB VM via `runner.rb` using the `dump_load0` binary. It includes the output showing the execution command, debug information, run result, and total cycles consumed (9239414). This represents running bytecode with a specific loader. ```Shell $ cd $TOP $ ckb-duktape/build/dump_bytecode ckb-duktape-template/build/duktape.js script.bin $ RUST_LOG=debug ./runner.rb ckb-duktape/build/dump_load0 script.bin dump0.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input -d dump0.bin DEBUG:: script group: Byte32(0xb5656359cbcd52cfa68e163cdd217657f0cfc533c909d13a1fdd8032f6b4f1f0) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 9239414 Transfer cycles: 67352, running cycles: 9172062 ``` -------------------------------- ### View Project Directory Structure Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx Execute the 'tree .' command from the project root to display the hierarchical structure of the generated project directory, including the newly created 'sudt' script boilerplate. ```bash tree . ``` -------------------------------- ### Creating WABT Main C File Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Uses a shell heredoc to create the C source file 'secp_wabt_main.c'. This file contains the main function for the WABT version, which loads witness data, initializes the secp library, and runs the secp verification function ('Z_runZ_ii') a specified number of times based on the loaded data. ```Shell cd $TOP cat << EOF > secp_wabt_main.c #include #include #include "ckb_syscalls.h" #include "secp.h" int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } init(); uint32_t times = value >> 8; value = value & 0xFF; uint8_t result = 0; for (int i = 0; i < times; i++) { result += Z_runZ_ii(value); } return result; } EOF ``` -------------------------------- ### Creating WAVM Main C File Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Uses a shell heredoc to create the C source file 'secp_wavm_main.c'. This file contains the main function for the WAVM version, which loads witness data and calls the WAVM-exported 'run' function ('wavm_exported_function_run') a specified number of times based on the loaded data. ```Shell cd $TOP cat << EOF > secp_wavm_main.c #include "secp_precompiled_glue.h" #include "abi/ckb_vm_wasi_abi.h" #include "ckb_syscalls.h" int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } uint32_t times = value >> 8; value = value & 0xFF; uint8_t result = 0; for (int i = 0; i < times; i++) { ckb_debug("One run!"); wavm_ret_int32_t wavm_ret = wavm_exported_function_run(NULL, value); result += wavm_ret.value; } return result; } EOF ``` -------------------------------- ### Compare Duktape Bytecode and Source File Sizes (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-9.md Uses the standard `ls -l` command to list the file sizes of the generated Duktape bytecode file (`script.bin`) and the original JavaScript source file (`duktape.js`). This snippet illustrates the size tradeoff discussed, showing that the bytecode file is often larger. ```Shell $ cd $TOP $ ls -l script.bin $ ls -l ckb-duktape-template/build/duktape.js ``` -------------------------------- ### Compiling ckb-duktape REPL Binary - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This snippet provides the bash commands necessary to clone the ckb-duktape repository, enter a docker container with the required RISC-V toolchain, and compile the duktape REPL binary (`build/repl`). It assumes docker and the specified nervos/ckb-riscv-gnu-toolchain image are available. ```bash $ git clone https://github.com/nervosnetwork/ckb-duktape $ cd ckb-duktape $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191012 bash root@982d1e906b76:/# cd /code root@982d1e906b76:/code# make riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror c/entry.c -c -o build/entry.o riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror duktape/duktape.c -c -o build/duktape.o riscv64-unknown-elf-gcc build/entry.o build/duktape.o -o build/duktape -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s riscv64-unknown-elf-gcc -Os -DCKB_NO_MMU -D__riscv_soft_float -D__riscv_float_abi_soft -Iduktape -Ic -Wall -Werror c/repl.c -c -o build/repl.o riscv64-unknown-elf-gcc build/repl.o build/duktape.o -o build/repl -lm -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s root@982d1e906b76:/code# exit ``` -------------------------------- ### Setting CKB dApp Network Environment (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/simple-lock.mdx This snippet shows how to configure the network environment for the CKB dApp by setting the `NEXT_PUBLIC_NETWORK` variable in the `.env` file. This allows switching between devnet, testnet, or mainnet. ```sh NEXT_PUBLIC_NETWORK=testnet # devnet, testnet or mainnet ``` -------------------------------- ### Running WAVM Benchmark (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Executes the patched WAVM binary (`secp_wavm_patched`) using the `runner.rb` script with input `0x01010000`. The output shows the run result (Ok(0)) and the total, transfer, and running cycles consumed by the CKB VM. ```text ``` -------------------------------- ### Build ckb-js-vm Binary (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Clones the ckb-js-vm repository, updates its submodules, and compiles the binary using the make command. Requires Clang ≥v18. ```sh git clone https://github.com/nervosnetwork/ckb-js-vm cd ckb-js-vm git submodule update --init make all ``` -------------------------------- ### Test ckb-js-vm with ckb-debugger (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Runs the compiled ckb-js-vm binary using the ckb-debugger tool to execute a test JavaScript file (tests/examples/hello.js). The --read-file option is for testing only. ```bash ckb-debugger --read-file tests/examples/hello.js --bin build/ckb-js-vm -- -r ``` -------------------------------- ### Patching WAVM Binary (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Patches the compiled WAVM binary (`secp_wavm`) using the `ckb-binary-patcher` tool, creating the final executable `secp_wavm_patched`. This step is necessary for the binary to be runnable on the CKB VM. ```Shell $ ckb-binary-patcher/target/release/ckb-binary-patcher -i secp_wavm -o secp_wavm_patched ``` -------------------------------- ### Run Project Unit Tests (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Command to execute the project's unit tests, typically defined in a `Makefile`. ```Bash make test ``` -------------------------------- ### Assemble Duktape Script Args (Variable JS) - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Uses a Docker container with the CKB RISC-V toolchain to run `native_args_assembler`. It creates a JavaScript file (`test.js`) with variable declarations and uses the assembler to generate the hexadecimal script arguments. ```Bash docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash cd /code echo "var a = 1;var b = a + 2;" >> test.js ./build/native_args_assembler -f test.js ``` -------------------------------- ### Generating New CKB Script 'caller' with make (Command) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx These commands navigate into the project directory and then execute the `make generate` command. This `make` target is used by the project template to create a new script module within the project, named `caller` in this case. ```bash cd caller-script make generate ``` -------------------------------- ### Run CKB Debugger with Dump File (Optimized) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Executes the script using the previously generated `dump0.bin` as input via `runner.rb` and `ckb-debugger`. This command demonstrates the reduced cycle consumption after applying optimizations, including skipping cleanup. ```Shell $ RUST_LOG=debug ./runner.rb dump0.bin script.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input DEBUG:: script group: Byte32(0x0e948e69dd75f2d6676048569073afe4ec2b284144bbe33a6216b13171606d18) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 3903352 Transfer cycles: 96994, running cycles: 3806358 ``` -------------------------------- ### Set Up and Interact with IPC Client (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/ckb-script-ipc.mdx Create an instance of the generated client struct (`WorldClient`), passing the `read_pipe` and `write_pipe` obtained during server initialization. You can then call the methods defined in the shared trait directly on the client instance to communicate with the server. ```Rust use crate::def::WorldClient; let mut client = WorldClient::new(read_pipe, write_pipe); let ret = client.hello("world".into()).unwrap(); ``` -------------------------------- ### Importing and Using Deployed Smart Contract Info in Frontend (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/examples/simple-lock/README.md Demonstrates how to import the configuration generated by `offckb` and construct a `CellDep` object required by CKB Lumos, using the automatically updated deployment details (transaction hash, index, and dependency type) for a specific script. ```ts import offckb from 'offckb.config'; import { CellDep } from '@ckb-lumos/lumos'; const lumosConfig = offckb.lumosConfig; const myContractDep: CellDep = { outPoint: { txHash: lumosConfig.SCRIPTS.YOUR_SCRIPT_NAME!.TX_HASH, index: lumosConfig.SCRIPTS.YOUR_SCRIPT_NAME!.INDEX, }, depType: lumosConfig.SCRIPTS.YOUR_SCRIPT_NAME!.DEP_TYPE, }; ``` -------------------------------- ### Depositing CKB to Hash Lock Address (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/simple-lock.mdx Uses the `offckb` tool to deposit 100 CKB tokens to a specific CKB address on the Devnet. This funds the address controlled by the deployed `hash_lock` script, preparing it for testing transfers. ```bash offckb deposit --network devnet ckt1qry2mh3j5cylve2tl2sjpg3zhp9wjeq2l92rvxtd2scsx4jks500xpqrnm4k4g7j8nlnyc0j3y3z5q6s5ns29k8wx9prkn8ff09mhepmagkhur6h 100 ``` ```text tx hash: 0x0668292c875ee31906e48651a553a16158307c02f2e91d24be75166ca080e1fd ``` -------------------------------- ### Listing Compiled Binaries (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Lists the file details (permissions, size, date) for the compiled WABT (`secp_wabt`) and patched WAVM (`secp_wavm_patched`) binaries using the `ls -l` command to compare their sizes. ```Shell $ ls -l secp_wabt secp_wavm_patched -rwxrwxr-x 1 ubuntu 1791744 Mar 3 05:27 secp_wabt* -rw-rw-r-- 1 ubuntu 1800440 Mar 3 05:29 secp_wavm_patched ``` -------------------------------- ### Create Spore DOB using Spore SDK (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/spore-dob-0.mdx Shows how to create a Spore DOB with `content_type` 'dob/0' using the `@spore-sdk/api` library, including setting content and linking to a cluster. ```JavaScript import { createSpore } from '@spore-sdk/api'; import { bytifyRawString } from '@spore-sdk/helpers/buffer'; const account = ...; const dob_cluster_id = ...; const dob_content = { dna: 'df4ffcb5e7a283ea7e6f09a504d0e256' }; const { txSkeleton, outputIndex } = await createSpore({ data: { contentType: 'dob/0', content: bytifyRawString(JSON.strinify(dob_content)), clusterId: dob_cluster_id }, fromInfos: [account.address], toLock: account.lock }); ``` -------------------------------- ### Enabling RPC Experiment Module (TOML) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/turn-on-fee-estimator.mdx This snippet demonstrates how to enable the 'Experiment' JSON-RPC API module in the [rpc] section of the ckb.toml file. Adding 'Experiment' to the 'modules' list makes experimental RPC methods, such as estimate_fee_rate, available for use. ```TOML [rpc] # List of API modules: ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment", "Debug", "Indexer"] modules = ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment", "Debug", "Indexer"] ``` -------------------------------- ### Connecting GDB to the Standalone Debugger Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md Shows the GDB commands and output for loading symbols from the script executable ('carrot') and connecting to the remote debugger instance running on a specified IP address and port. ```GDB GNU gdb (GDB) 8.3.0.20190516-git Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from carrot... (gdb) target remote 192.168.1.230:2000 Remote debugging using 192.168.1.230:2000 0x00000000000100c6 in _start () (gdb) ``` -------------------------------- ### Implement CKB Contract Callee Logic in Rust Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Provides the main entry point `program_entry` and the core `callee` function for a CKB contract. The `callee` function retrieves arguments, inherits file descriptors (pipes), concatenates arguments, and writes the result to the parent process via a pipe using the `write` syscall. ```Rust mod error; use alloc::vec; pub fn program_entry() -> i8 { ckb_std::debug!("Enter callee contract!"); match callee() { Ok(_) => 0, Err(err) => err as i8, } } pub fn callee() -> Result<(), error::Error> { let argv = ckb_std::env::argv(); let mut to_parent_fds: [u64; 2] = [0; 2]; ckb_std::syscalls::inherited_fds(&mut to_parent_fds); let mut out = vec![]; for arg in argv { out.extend_from_slice(arg.to_bytes()); } let len = ckb_std::syscalls::write(to_parent_fds[1], &out)?; assert_eq!(len, 10); Ok(()) } ``` -------------------------------- ### Implementing Caller Function with Pipes and Spawn (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Implements the core logic of the caller script. It creates two pipes for bidirectional communication, sets up arguments for the `spawn` syscall, executes another script (assumed to be in the first Cell Dep), reads the result from the pipe, and asserts the expected output. ```Rust fn caller() -> Result<(), error::Error> { let (r1, w1) = ckb_std::syscalls::pipe()?; let (r2, w2) = ckb_std::syscalls::pipe()?; let to_parent_fds: [u64; 2] = [r1, w2]; let to_child_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 let mut pid: u64 = 0; let place = 0; // 0 means read from cell data let bounds = 0; // 0 means read to end let argc: u64 = 2; let argv = [ CStr::from_bytes_with_nul(b"hello\0").unwrap().as_ptr(), CStr::from_bytes_with_nul(b"world\0").unwrap().as_ptr(), ]; let mut spgs: SpawnArgs = SpawnArgs { argc, argv: argv.as_ptr(), process_id: &mut pid as *mut u64, inherited_fds: to_child_fds.as_ptr(), }; ckb_std::syscalls::spawn( 0, ckb_std::ckb_constants::Source::CellDep, place, bounds, &mut spgs, )?; let mut buf = [0; 256]; let len = ckb_std::syscalls::read(to_parent_fds[0], &mut buf)?; assert_eq!(len, 10); buf[len] = 0; assert_eq!( CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(), "helloworld" ); Ok(()) } ``` -------------------------------- ### Assembling Duktape Script Arguments (Bash) - Different JS Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md Uses the `native_args_assembler` tool within a Docker container to generate hexadecimal script arguments from a different JavaScript source file (`test.js`). ```Bash docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash cd /code echo "var a = 1;var b = a + 2;" >> test.js ./build/native_args_assembler -f test.js ``` -------------------------------- ### Compile JavaScript to Binary (Shell - gawk) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Provides an alternative compilation command specifically for macOS users. It performs the same compilation process as the previous snippet but uses 'gawk' instead of 'awk', which might be necessary on some macOS systems. ```Shell ckb-debugger --read-file js/hello.js --bin deps/ckb-js-vm -- -c | gawk -f deps/compile.awk | xxd -r -p > js/build/hello.bc ``` -------------------------------- ### Deploy CKB Script (Specify Config Path) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Deploy the built CKB script to a specified network, providing an explicit path to the `offckb.config.ts` file. ```bash offckb deploy --network --config ``` -------------------------------- ### Navigate to CKB Directory (Mac/Windows) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-testnet-node.mdx Change the current directory in the terminal to the unzipped CKB binary location, specific to macOS or Windows. ```bash cd /Users/(NAME)/Documents/ckb_v0.115.0-rc3_aarch64-apple-darwin-portable/ckb ``` ```bash cd C:/ckb_v0.115.0_x86_64-pc-windows-msvc ``` -------------------------------- ### Use entry_simulator! Macro in Simulator Lib (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Invokes the `ckb_std::entry_simulator!` macro in the simulator library's `lib.rs`. This macro sets up the entry point for the native simulator, directing it to call the `program_entry` function from the main contract crate. ```Rust ckb_std::entry_simulator!(::program_entry); ``` -------------------------------- ### Creating Minimal CKB Script C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This snippet shows the most basic CKB script written in C. It defines a standard `main` function that takes command-line arguments and simply returns 0. In the CKB VM, a return code of 0 signifies successful script execution, making this a script that always passes validation. ```C int main(int argc, char* argv[]) { return 0; } ``` -------------------------------- ### Define Simple JavaScript Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Provides the content for the 'hello.js' file. This is a basic JavaScript script that prints a greeting message to the console when executed by the ckb-js-vm. ```JavaScript console.log("hello, ckb-js-script!"); ``` -------------------------------- ### Building CKB Transaction in REPL (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx REPL commands using the CCC SDK to construct a CKB transaction that utilizes the deployed `ckb-js-vm` and `hello.bc` scripts. It sets up the output cell's type script args and includes necessary cell dependencies. ```sh OffCKB > let baseScriptArgs = `0x0000${myScripts['hello.bc'].codeHash.slice(2)}0${ccc.hashTypeToBytes(myScripts['hello.bc'].hashType).toString()}`; OffCKB > let baseScript = ccc.Script.from({ ... codeHash: myScripts["ckb-js-vm"].codeHash, ... hashType: myScripts["ckb-js-vm"].hashType, ... args: baseScriptArgs, ... }) ``` ```sh OffCKB > let tx = ccc.Transaction.from({ ... outputs: [ ... { ... lock: accounts[0].lockScript, ... type: baseScript ... }, ... ], ... cellDeps: [ ... ...myScripts["ckb-js-vm"].cellDeps.map(c => c.cellDep), ... ...myScripts['hello.bc'].cellDeps.map(c => c.cellDep) ... ], ... }); ``` -------------------------------- ### Navigate to CKB Directory (Mac) - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-mainnet-node.mdx Changes the current directory in the terminal to the location where the CKB binary was unzipped on macOS. Replace `(NAME)` with your actual username. ```bash cd /Users/(NAME)/Documents/ckb_v0.115.0-rc3_aarch64-apple-darwin-portable/ckb ``` -------------------------------- ### Create Script-Only OffCKB Project Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Generate a new project focused solely on developing CKB smart contracts (scripts) without including a frontend boilerplate. ```bash offckb create --script ``` -------------------------------- ### Compiling WABT and WAVM Binaries (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Compiles the WABT and WAVM versions of the secp256k1 test program using `riscv64-unknown-elf-gcc` within a docker container. The WABT version links against `secp.c` and `wasm-rt-impl.c`, while the WAVM version links against the AOT runtime and the precompiled object file. ```Shell $ cd $TOP $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@a237c0d00b1c:/# cd /code/ root@a237c0d00b1c:/code# riscv64-unknown-elf-gcc -O3 -I ckb-c-stdlib -I wavm-aot-generator -I wabt/wasm2c secp_wabt_main.c secp.c wabt/wasm2c/wasm-rt-impl.c -o secp_wabt root@a237c0d00b1c:/code# riscv64-unknown-elf-gcc -O3 -I ckb-c-stdlib -I wavm-aot-generator -I wabt/wasm2c secp_wavm_main.c wavm-aot-generator/abi/riscv64_runtime.S secp_precompiled.o -o secp_wavm -Wl,-T wavm-aot-generator/abi/riscv64.lds root@a237c0d00b1c:/code# exit exit ``` -------------------------------- ### Benchmarking WAVM Binary (1 Iteration) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Runs the patched WAVM compiled binary (secp_wavm_patched) using the runner.rb script with input 0x01010000. This input likely encodes the number of iterations (1) and the specific test case (0x01). The output shows the run result and cycle consumption. ```Shell ./runner.rb secp_wavm_patched 0x01010000 ``` -------------------------------- ### Configuring Lumos SDK for CKB Testnet (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/blockchain-networks.mdx This snippet shows how to initialize the Lumos SDK to connect to the CKB Testnet. It sets up the Indexer and RPC clients using the Testnet RPC URL and initializes the Lumos configuration for the Testnet environment. ```JavaScript const lumos = require("@ckb-lumos/lumos"); const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); lumos.config.initializeConfig(lumos.config.TESTNET); ``` -------------------------------- ### WAVM C Wrapper for CKB - C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md This C code provides a wrapper for the WAVM precompiled WASM output. It includes necessary headers, defines a `wavm_env_abort` function that uses `ckb_exit`, loads input data from the CKB witness, calls the WAVM-exported `fib` function, and returns its result. ```C #include "fib_precompiled_glue.h" #include "abi/ckb_vm_wasi_abi.h" #include "ckb_syscalls.h" void* wavm_env_abort(void* dummy, int32_t code, int32_t a, int32_t b, int32_t c) { ckb_exit(code); return dummy; } int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } wavm_ret_int32_t wavm_ret = wavm_exported_function_fib(NULL, value); return wavm_ret.value; } ``` -------------------------------- ### Initial C Wrapper for WASM-to-C Code Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-4.md A C program (main.c) that includes the generated fib.h, reads an integer argument, initializes the WASM runtime (init()), calls the fib function (Z_fibZ_ii), and returns the result. ```C #include #include #include "fib.h" int main(int argc, char** argv) { if (argc < 2) return 2; u8 x = atoi(argv[1]); init(); u8 result = Z_fibZ_ii(x); return result; } ``` -------------------------------- ### Navigate to Light Client Directory (Windows Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Bash command used on Windows (likely via a compatible shell like Git Bash or WSL) to change the current working directory to the folder containing the CKB light client binary and configuration file. ```bash cd C:/(YOUR_FOLDER_NAME) ``` -------------------------------- ### Initialize IPC Server (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/ckb-script-ipc.mdx Initialize the IPC server by calling `spawn_server`. This function sets up the communication pipes (`read_pipe`, `write_pipe`) needed for the client to interact with the server. Parameters specify the script index, source (e.g., `CellDep`), and any arguments. ```Rust use ckb_script_ipc_common::spawn::spawn_server; let (read_pipe, write_pipe) = spawn_server( 0, Source::CellDep, &[CString::new("demo").unwrap().as_ref()], )?; ``` -------------------------------- ### Building and Sending CKB Transaction with Duktape Script (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md Demonstrates the full process of creating a transaction, adding a transfer, attaching a Duktape type script to an output cell, adding the Duktape cell dependency, paying fees, preparing for signing, signing, sealing, and sending the transaction to the CKB network. ```JavaScript const duktapeTypeScript = { codeHash: duktapeCodeHash, hashType: "data", args: "0x370000000c00000033000000000000001f000000434b422e6465627567282249276d2072756e6e696e6720696e204a5322290a04000000" }; let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"200" + "00000000"); txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.cellOutput.type = duktapeTypeScript; return outputs; }); txSkeleton = lumos.helpers.addCellDep(txSkeleton, { outPoint: { txHash: duktapeTxHash, index: "0x0" }, depType: "code" }) txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) const txHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### Stepping Through Script Execution in GDB Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md Illustrates a GDB debugging session, including setting a breakpoint at 'main', continuing execution, stepping through lines ('n'), inspecting variable values ('p'), and identifying a logic error related to the interpretation of memcmp's return value. ```GDB (gdb) b main Breakpoint 1 at 0x106b0: file carrot.c, line 6. (gdb) c Continuing. Breakpoint 1, main (argc=0, argv=0x400000) at carrot.c:6 6 size_t index = 0; (gdb) n 7 uint64_t len = 0; (gdb) n 11 len = 6; (gdb) n 12 memset(buffer, 0, 6); (gdb) n 13 ret = ckb_load_cell_data(buffer, &len, 0, index, CKB_SOURCE_OUTPUT); (gdb) n 14 if (ret == CKB_INDEX_OUT_OF_BOUND) { (gdb) n 18 int cmp = memcmp(buffer, "carrot", 6); (gdb) n 19 if (cmp) { (gdb) p cmp $1 = -99 (gdb) p buffer[0] $2 = 0 '\000' (gdb) n 20 return -1; ``` -------------------------------- ### Patching WAVM Binary Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Uses the ckb-binary-patcher tool to patch the compiled WAVM binary (secp_wavm), creating a new patched binary (secp_wavm_patched). This step is likely necessary to prepare the binary for execution within the CKB VM environment. ```Shell ckb-binary-patcher/target/release/ckb-binary-patcher -i secp_wavm -o secp_wavm_patched ``` -------------------------------- ### Deploy Upgradable CKB Script Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Deploy the built CKB script to a specified network, adding the `--type-id` flag to make the script upgradable. ```bash cd frontend && offckb deploy --type-id --network ``` -------------------------------- ### Navigate to Light Client Directory (Mac Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/node/run-light-client-node.mdx Bash command used on macOS to change the current working directory to the specific folder where the CKB light client binary and configuration file have been placed, preparing for execution. ```bash cd /Users/(NAME)/Documents/(YOUR_FOLDER_NAME) ``` -------------------------------- ### Benchmarking WAVM Binary (5 Iterations) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Runs the patched WAVM compiled binary (secp_wavm_patched) using the runner.rb script with input 0x01050000. This input likely encodes the number of iterations (5) and the specific test case (0x01). The output shows the run result and cycle consumption. ```Shell ./runner.rb secp_wavm_patched 0x01050000 ``` -------------------------------- ### Build CKB Script Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Compile the smart contract code within your project. This command typically uses a Makefile to orchestrate the build process. ```bash make build ``` -------------------------------- ### Preparing Compiled Rust Scripts for Debugging (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Copies the compiled script binary to create a `.debug` version (with symbols) and then uses `llvm-objcopy` to strip debug information and symbols from the original binary, resulting in two files: one for debugging and one for deployment. ```Shell cp .debug llvm-objcopy --strip-debug --strip-all ``` -------------------------------- ### Create Transaction Using Script as Type (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Demonstrates creating a new transaction skeleton using Lumos and setting the previously defined `carrotTypeScript` as the `type` script of one of the output cells. It first creates a basic transfer transaction and then updates the first output cell to include the `carrotTypeScript`. This prepares the transaction to execute the script when the output cell is consumed. ```js > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address], wallet2.address,"100" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.cellOutput.type = carrotTypeScript; return outputs; }); ``` -------------------------------- ### Response from Script Boilerplate Generation Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx This output shows the console response after running 'make generate', confirming that the boilerplate for the 'sudt' script has been successfully created within the project. ```bash 🤷 Project Name: sudt 🔧 Destination: /tmp/sudt-script/contracts/sudt ... 🔧 project-name: sudt ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/sudt-script/contracts/sudt`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/sudt-script/contracts/sudt ``` -------------------------------- ### Configure Next.js dApp Network in .env (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/getting-started/blockchain-networks.mdx Modifies the NEXT_PUBLIC_NETWORK environment variable in the .env file to specify the desired CKB network for the Next.js dApp. Choose 'devnet', 'testnet', or 'mainnet'. ```bash NEXT_PUBLIC_NETWORK=testnet # or testnet, mainnet ``` -------------------------------- ### Compiling Native C Benchmark with RISC-V GCC Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Executes compilation steps inside a Docker container using the nervos/ckb-riscv-gnu-toolchain. It navigates to the ckb-vm-bench-scripts directory and runs 'make' to compile the native C secp256k1 benchmark. ```Shell sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@ad22c452cb54:/# cd /code/ckb-vm-bench-scripts root@ad22c452cb54:/code/ckb-vm-bench-scripts# make (omitted ...) root@ad22c452cb54:/code/ckb-vm-bench-scripts# exit exit ``` -------------------------------- ### Running WABT Benchmark (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Executes the WABT compiled binary (`secp_wabt`) using the `runner.rb` script with input `0x01010000`. The output shows the run result (Ok(0)) and the total, transfer, and running cycles consumed by the CKB VM. ```Shell $ ./runner.rb secp_wabt 0x01010000 Run result: Ok(0) Total cycles consumed: 35702943 Transfer cycles: 438060, running cycles: 35264883 ``` -------------------------------- ### Response: Create New Script Module - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx Expected output from the `make generate` command. It shows the process of generating the template for the new 'carrot' script module within the workspace. ```Bash 🤷 Project Name: carrot 🔧 Destination: /tmp/my-first-contract-workspace/contracts/carrot ... 🔧 project-name: carrot ... 🔧 Generating template ... 🔧 Moving generated files into: `/tmp/my-first-contract-workspace/contracts/carrot`... 🔧 Initializing a fresh Git repository ✨ Done! New project created /tmp/my-first-contract-workspace/contracts/carrot ``` -------------------------------- ### Signing and Sending CKB Transaction (Go) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Demonstrates how to sign a prepared CKB transaction using a private key and then send it to a CKB node. Requires a TransactionWithScriptGroups object and a private key string. Uses ckbClient to send the transaction. ```Go // Your built txWithScriptGroups var txWithScriptGroups *transaction.TransactionWithScriptGroups // 0. Set your private key privKey := "0xccb083b37aa346c5ce2e1f99a687a153baa04052f26db6ab3c26d6a4cc15c5f1" // 1. Sign transaction with your private key txSigner := signer.GetTransactionSignerInstance(types.NetworkTest) txSigner.SignTransactionByPrivateKeys(txWithScriptGroups, privKey) // 2. Send transaction to CKB node txHash, err := ckbClient.SendTransaction(context.Background(), txWithScriptGroups.TxView) ``` -------------------------------- ### Build Rust Project (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/rust.mdx Command to compile the Rust project and its dependencies using Cargo. ```Bash cargo build ``` -------------------------------- ### Simplified Generated IPC Server Implementation - Rust Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/ckb-script-ipc.mdx Presents a simplified version of the server-side code generated by the `#[ckb_script_ipc::service]` macro. It implements the `ckb_script_ipc_common::ipc::Serve` trait, handling incoming requests, dispatching them to the actual service implementation, and returning the appropriate response. ```rust impl ckb_script_ipc_common::ipc::Serve for ServeWorld where S: World, { type Req = WorldRequest; type Resp = WorldResponse; fn serve( &mut self, req: WorldRequest, ) -> ::core::result::Result< WorldResponse, ckb_script_ipc_common::error::IpcError, > { match req { WorldRequest::Hello { name } => { let ret = self.service.hello(name); Ok(WorldResponse::Hello(ret)) } } } } ``` -------------------------------- ### Adding CKB-SDK-Java Dependencies to build.gradle Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/java.mdx Configuration snippet for the build.gradle file to include the necessary CKB-SDK-Java modules as project dependencies. ```Gradle dependencies { implementation 'org.nervos.ckb:ckb:{version}' implementation 'org.nervos.ckb:core:{version}' implementation 'org.nervos.ckb:utils:{version}' } ``` -------------------------------- ### Deploy CKB Script using Lumos SDK Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This JavaScript code snippet uses the Lumos SDK to deploy the compiled CKB script (`carrot_bug`) onto the CKB testnet. It reads the script binary, creates a transaction skeleton, transfers funds, attaches the script binary as cell data, pays the fee, prepares signing entries, signs the transaction, and sends it to the RPC endpoint. ```JavaScript > const lumos = require("@ckb-lumos/lumos"); > const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); > const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); > lumos.config.initializeConfig(lumos.config.TESTNET); > const wallet = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqvwg2cen8extgq8s5puft8vf40px3f599cytcyd8", privkey: "0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6" }; > const wallet2 = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2prryvze6fhufxkgjx35psh7w70k3hz7c3mtl4d", privkey: "0xace08599f3174f4376ae51fdc30950d4f2d731440382bb0aa1b6b0bd3a9728cd" } > const data = fs.readFileSync("carrot_bug"); > data.byteLength 19760 > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"19900" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); > txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); > txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); > const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); > const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) > const carrotTxHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### Create New Script Module - Bash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/a-minimal-script.mdx Commands to navigate into the newly created workspace and run the `make generate` command to add a new script module named 'carrot' within the workspace. ```Bash cd my-first-contract-workspace make generate ``` -------------------------------- ### Assembling Duktape Script Arguments (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md Uses the `native_args_assembler` tool within a Docker container to generate hexadecimal script arguments from a JavaScript source file (`test.js`). ```Bash docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash cd /code echo "CKB.debug(\"I'm running in JS\")" > test.js ./build/native_args_assembler -f test.js ``` -------------------------------- ### Running WABT Benchmark (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-8.md Executes the WABT compiled binary (`secp_wabt`) using the `runner.rb` script with input `0x01050000`. The output shows the run result (Ok(0)) and the total, transfer, and running cycles consumed by the CKB VM for a different input value. ```Shell $ ./runner.rb secp_wabt 0x01050000 Run result: Ok(0) Total cycles consumed: 90164183 Transfer cycles: 438060, running cycles: 89726123 ``` -------------------------------- ### Create Cluster using Spore SDK (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/common-scripts/spore-dob-0.mdx Demonstrates how to create a Cluster using the `@spore-sdk/api` library, including setting metadata and specifying sender and receiver locks. ```JavaScript import { createCluster } from '@spore-sdk/api'; import { bytifyRawString } from '@spore-sdk/helpers/buffer'; const account = ...; const dob_metadata = { description: 'this is the description for cluster', dob: { ver: 0, decoder: { type: 'code_hash', hash: '...' }, pattern: [["Age", "number", 1, 1, "range", [0, 100]]] } }; const { txSkeleton, outputIndex } = await createCluster({ data: { name: 'My First DOB Cluster', description: bytifyRawString(JSON.strinify(dob_metadata)) }, fromInfos: [account.address], toLock: account.lock }); ``` -------------------------------- ### Output of Project Directory Structure Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx This output shows the directory tree structure of the 'sudt-script' project after initialization and script generation, highlighting the location of the 'sudt' script source file ('contracts/sudt/src/main.rs'). ```bash . ├── Cargo.toml ├── Makefile ├── README.md ├── contracts │   └── sudt │   ├── Cargo.toml │   ├── Makefile │   ├── README.md │   └── src │   └── main.rs ├── scripts │   ├── find_clang │   └── reproducible_build_docker └── tests ├── Cargo.toml └── src ├── lib.rs └── tests.rs 7 directories, 12 files ``` -------------------------------- ### Defining Program Entry and Caller Function Signature (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/spawn-script.mdx Defines the main entry point `program_entry` for the CKB script, which calls the `caller` function. It handles the result of `caller`, returning 0 on success or the error code on failure. The signature for the `caller` function is also defined. ```Rust pub fn program_entry() -> i8 { ckb_std::debug!("Enter caller contract!"); match caller() { Ok(_) => 0, Err(err) => err as i8, } } fn caller() -> Result<(), error::Error> {} ``` -------------------------------- ### Sign and Send CKB Transaction (Success) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This snippet demonstrates how to sign a prepared transaction skeleton using a private key and send it to the CKB network via an RPC client. It assumes the transaction skeleton is valid and passes script validation. ```JavaScript const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures) const txHash = await rpc.sendTransaction(signedTx) ``` -------------------------------- ### Change Directory Inside Docker (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Changes the current directory inside the Docker container to /code, where the C source file was mounted. ```Shell root@57b79063c965:/# cd /code ``` -------------------------------- ### Compile C Program to RISC-V using Docker Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-4.md Commands executed within a Docker container to compile the C source files (`main.c`, `fib.c`, `wasm-rt-impl.c`) into a RISC-V executable (`fib_riscv64`) using the provided Docker image and RISC-V GNU toolchain. ```Shell $ sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash (docker) $ cd /code (docker) $ riscv64-unknown-elf-gcc -o fib_riscv64 -O3 -g main.c fib.c /code/wabt/wasm2c/wasm-rt-impl.c -I /code/wabt/wasm2c (docker) $ exit ``` -------------------------------- ### Compiling WABT and WAVM Binaries with RISC-V GCC Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Executes compilation steps inside a Docker container using the nervos/ckb-riscv-gnu-toolchain. It compiles the WABT version (secp_wabt_main.c, secp.c, wasm-rt-impl.c) and the WAVM version (secp_wavm_main.c, riscv64_runtime.S, secp_precompiled.o) into RISC-V executables. ```Shell cd $TOP sudo docker run --rm -it -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20191209 bash root@a237c0d00b1c:/# cd /code/ root@a237c0d00b1c:/code# riscv64-unknown-elf-gcc -O3 -I ckb-c-stdlib -I wavm-aot-generator -I wabt/wasm2c secp_wabt_main.c secp.c wabt/wasm2c/wasm-rt-impl.c -o secp_wabt root@a237c0d00b1c:/code# riscv64-unknown-elf-gcc -O3 -I ckb-c-stdlib -I wavm-aot-generator -I wabt/wasm2c secp_wavm_main.c wavm-aot-generator/abi/riscv64_runtime.S secp_precompiled.o -o secp_wavm -Wl,-T wavm-aot-generator/abi/riscv64.lds root@a237c0d00b1c:/code# exit exit ``` -------------------------------- ### Building CKB Transaction with Lumos (Duktape Script) - JavaScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Initializes a Lumos transaction skeleton, adds a transfer output, updates the output cell to include the duktape type script, adds the duktape script code as a cell dependency, pays the fee, prepares signing entries, signs the transaction, and sends it to the RPC. ```JavaScript const duktapeTypeScript = { codeHash: duktapeCodeHash, hashType: "data", args: "0x370000000c00000033000000000000001f000000434b422e6465627567282249276d2072756e6e696e6720696e204a5322290a04000000" }; let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"200" + "00000000"); txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.cellOutput.type = duktapeTypeScript; ``` -------------------------------- ### Benchmarking WABT Binary (1 Iteration) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Runs the WABT compiled binary (secp_wabt) using the runner.rb script with input 0x01010000. This input likely encodes the number of iterations (1) and the specific test case (0x01). The output shows the run result and cycle consumption. ```Shell ./runner.rb secp_wabt 0x01010000 ``` -------------------------------- ### Generate Molecule Bindings (Folder) - OffCKB CLI Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Generate code bindings for a specific programming language from all Molecule schema files within a specified folder. Specify the input schema folder, the desired output folder path, and the target language. ```bash offckb mol --schema --output-folder --lang ``` -------------------------------- ### Run CKB Debugger with Dump File (No Cleanup) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Executes the `dump_load0_nocleanup` version of the script using `runner.rb`, piping the execution through `ckb-debugger` with a specified dump file (`dump0.bin`). This command demonstrates the cycle consumption before applying further optimizations. ```Shell $ cd $TOP $ RUST_LOG=debug ./runner.rb ckb-duktape/build/dump_load0_nocleanup script.bin dump0.bin Executing: ckb-standalone-debugger/bins/target/release/ckb-debugger --tx-file tx.json --script-group-type lock -i 0 -e input -d dump0.bin DEBUG:: script group: Byte32(0x06034ffb00fec553882c6a9c7614333a728828772d3c236a7f8fa6af60669538) DEBUG OUTPUT: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd970dd9a8 Run result: Ok(0) Total cycles consumed: 7856033 Transfer cycles: 67348, running cycles: 7788685 ``` -------------------------------- ### Listing Compiled Binary Sizes Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Uses the 'ls -l' command to display the file sizes of the compiled WABT binary (secp_wabt) and the patched WAVM binary (secp_wavm_patched), allowing for a comparison of their on-disk sizes. ```Shell ls -l secp_wabt secp_wavm_patched ``` -------------------------------- ### Export OffCKB System Scripts in Lumos Format Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Shows the command to export information about the built-in system scripts in a format compatible with the Lumos SDK. ```bash offckb system-scripts --export-style lumos ``` -------------------------------- ### Create Class with Codec Decorator - JavaScript Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/serialization/ccc-molecule.mdx Demonstrates using the `@mol.codec` decorator from CKB-CCC to simplify creating codec bindings for a JavaScript class (`Monster`). The class extends `mol.Entity.Base`, includes a constructor for initializing properties, and shows how to add custom methods and serialize the instance to bytes. ```javascript @mol.codec(MonsterCodec) export class Monster extends mol.Entity.Base() { constructor(monster: MonsterLike){ super(); this.hp = +ccc.numFrom(monster.hp).toString(10); this.damage = +ccc.numFrom(monster.damage).toString(10); } customMethod(){ console.log("calling monster custom method"); } } const myMonster = new Monster({hp: 100, damage: 10}); myMonster.customMethod(); console.log("monster mol serialized: ", myMonster.toBytes()) ``` -------------------------------- ### Generate New Script Boilerplate Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx Navigate into the newly created project directory and run the 'make generate' command. This command uses the project's Makefile to generate boilerplate code for a new script named 'sudt' within the project structure. ```bash cd sudt-script make generate ``` -------------------------------- ### List Fibonacci Binary Sizes (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Lists the file sizes of the three different fibonacci binary versions (native, WABT, WAVM patched) using the long format. ```Shell $ ls -lh fib_wabt fib_wavm_patched fib_native -rwxr-xr-x 1 root 11K Mar 3 03:27 fib_native* -rwxr-xr-x 1 root 53K Mar 3 03:26 fib_wabt* -rwxr-xr-x 1 root 88K Mar 3 03:26 fib_wavm_patched* ``` -------------------------------- ### Debugging CKB Transaction Execution (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Command and output for debugging a specific transaction using `offckb debug`. The output shows the execution results and logs for each script involved, confirming the `hello.js` script ran successfully. ```sh offckb debug --tx-hash 0x1464fec71bd95c4caa2a2640f15738 ``` -------------------------------- ### Deploying CKB Script Binary with Lumos (Javascript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-5.md Javascript code using the Lumos SDK to deploy a compiled CKB script binary (`carrot_bug`) onto the CKB testnet. Reads the binary file, creates a transaction, sets the binary as cell data, signs, and sends the transaction. ```Javascript const lumos = require("@ckb-lumos/lumos"); const indexer = new lumos.Indexer("https://testnet.ckb.dev/rpc"); const rpc = new lumos.RPC("https://testnet.ckb.dev/rpc"); lumos.config.initializeConfig(lumos.config.TESTNET); const wallet = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqvwg2cen8extgq8s5puft8vf40px3f599cytcyd8", privkey: "0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6", }; const wallet2 = { address: "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2prryvze6fhufxkgjx35psh7w70k3hz7c3mtl4d", privkey: "0xace08599f3174f4376ae51fdc30950d4f2d731440382bb0aa1b6b0bd3a9728cd" } const data = fs.readFileSync("carrot_bug"); data.byteLength; let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"19900" + "00000000"); txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.data = "0x" + data.toString("hex"); return outputs; }); txSkeleton = await lumos.commons.common.payFeeByFeeRate(txSkeleton,[wallet.address],1000); txSkeleton = lumos.commons.common.prepareSigningEntries(txSkeleton); const signatures = txSkeleton.get("signingEntries").map((entry) => lumos.hd.key.signRecoverable(entry.message, wallet.privkey)).toArray(); const signedTx = lumos.helpers.sealTransaction(txSkeleton, signatures); const carrotTxHash = await rpc.sendTransaction(signedTx); ``` -------------------------------- ### Benchmarking WABT Binary (5 Iterations) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Runs the WABT compiled binary (secp_wabt) using the runner.rb script with input 0x01050000. This input likely encodes the number of iterations (5) and the specific test case (0x01). The output shows the run result and cycle consumption. ```Shell ./runner.rb secp_wabt 0x01050000 ``` -------------------------------- ### Compile JavaScript to Binary (Shell - awk) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx Compiles the 'hello.js' script into a binary format ('hello.bc') suitable for the ckb-js-vm. It uses ckb-debugger to read the JS file, pipes the output through 'awk' for processing (using 'compile.awk'), and then uses 'xxd' to convert the hex output to binary. ```Shell ckb-debugger --read-file js/hello.js --bin deps/ckb-js-vm -- -c | awk -f deps/compile.awk | xxd -r -p > js/build/hello.bc ``` -------------------------------- ### Generate Molecule Bindings (File) - OffCKB CLI Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Generate code bindings for a specific programming language from a single Molecule schema (.mol) file. Specify the input schema file, the desired output file path, and the target language. ```bash offckb mol --schema --output --lang ``` -------------------------------- ### Signing and Sending CKB Transaction in REPL (sh) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/js-script.mdx REPL commands using the CCC SDK to complete the transaction inputs and fee, sign the transaction using a private key, and send it to the CKB devnet. ```sh OffCKB > let signer = new ccc.SignerCkbPrivateKey(client, accounts[0].privkey); OffCKB > await tx.completeInputsByCapacity(signer); 2 OffCKB > await tx.completeFeeBy(signer, 1000); [ 0, true ] OffCKB > await signer.sendTransaction(tx); '0x1464fec71bd95c4caa2a2640f1573850b25ba9c696c1bfdbe0dc7459717c734b' OffCKB > ``` -------------------------------- ### Converting Public Key to CKB Address (Go) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/go.mdx Illustrates how to create a secp256k1_blake160_signhash_all lock script directly from a compressed elliptic curve public key string (33 bytes). This script is then used to construct a CKB address object for the test network. ```Go // You should provide an elliptic curve public key of compressed format, with 33 bytes. script, err := systemscript.Secp256K1Blake160SignhashAllByPublicKey("0x03a0a7a7597b019828a1dda6ed52ab25181073ec3a9825d28b9abbb932fe1ec83d") if err != nil { // handle error } addr := &address.Address{Script: script, Network: types.NetworkTest} ``` -------------------------------- ### Configuring CKB CCC Provider (TypeScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/integrate-wallets/ccc-wallet.mdx Shows how to wrap the application with the `ccc.Provider` from `@ckb-ccc/connector-react` to configure wallet connection options, including network selection (mainnet/testnet) and custom styling for the connector UI. ```typescript import React from "react"; import { ccc } from "@ckb-ccc/connector-react"; import { CSSProperties } from "react"; export function LayoutProvider({ children }: { children: React.ReactNode }) { const defaultClient = React.useMemo(() => { return process.env.REACT_APP_IS_MAINNET === "true" ? new ccc.ClientPublicMainnet() : new ccc.ClientPublicTestnet(); }, []); return ( {children} ); } ``` -------------------------------- ### Deploy CKB Script (Default Config) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Deploy the built CKB script to a specified network (devnet or testnet). This command assumes the `offckb.config.ts` file is located in the frontend directory. ```bash cd frontend && offckb deploy --network ``` -------------------------------- ### Implement createSporeDOB Function Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/dapp/create-dob.mdx Provides the full TypeScript implementation of the `createSporeDOB` function using the Spore-SDK. It demonstrates creating a wallet from a private key, building a Spore creation transaction with specified content type and content, and finally signing and sending the transaction to the network. ```ts export async function createSporeDOB( privkey: string, content: Uint8Array ): Promise<{ txHash: string; outputIndex: number }> { const wallet = createDefaultLockWallet(privkey); const { txSkeleton, outputIndex } = await createSpore({ data: { contentType: "image/jpeg", content, }, toLock: wallet.lock, fromInfos: [wallet.address], config: SPORE_CONFIG, }); const txHash = await wallet.signAndSendTransaction(txSkeleton); console.log(`Spore created at transaction: ${txHash}`); console.log( `Spore ID: ${ txSkeleton.get("outputs").get(outputIndex)!.cellOutput.type!.args }` ); return { txHash, outputIndex }; } ``` -------------------------------- ### Compile CKB C Script (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Compiles the c.c source file into a RISC-V executable named 'c' using the cross-compilation toolchain inside the Docker container, applying optimizations for size. ```Shell root@57b79063c965:/code# riscv64-unknown-elf-gcc -O3 -I ckb-duktape/deps/ckb-c-stdlib -I ckb-duktape/deps/molecule c.c -o c -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s ``` -------------------------------- ### Configure Simulator Library Cargo.toml (TOML) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Configures the `Cargo.toml` for the simulator library. It adds the main contract crate and `ckb-std` as dependencies, enabling the `native-simulator` feature for both. It also sets the crate type to `cdylib` for dynamic library compilation. ```TOML [dependencies] contract = { path = "../../contracts/contract", features = ["native-simulator"] } ckb-std = { version = "0.16.3", features = ["native-simulator"] } [lib] crate-type = ["cdylib"] ``` -------------------------------- ### Navigate to Devnet Configuration Directory Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/offckb.mdx Change the current directory to the location where OffCKB stores the devnet configuration files. This allows modification of network settings. ```bash cd ``` -------------------------------- ### Rendering Development & Deployment Cards (JSX) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/sdk-and-devtool/devtool.md This JSX snippet maps over the first two elements of the `toolCardContents` array to render a list of development and deployment tools using the `Card` component. It passes properties like `index`, `title`, `description`, `link`, `type`, and `links` to each `Card`. ```jsx {toolCardContents.slice(0, 2).map(({ index, title, description, link, type, links }) => ( ))} ``` -------------------------------- ### Assembling UDT Script Arguments (Bash) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-3.md This bash snippet shows how to use the `native_args_assembler` tool within a Docker container to generate the arguments required for the UDT script. It takes the UDT script file (`udt.js`) and the input cell's outpoint (obtained from the previous step) as parameters. ```bash cd ckb-duktape docker run --rm -it -v \`pwd\`:/code nervos/ckb-riscv-gnu-toolchain:xenial bash root@0d31cad7a539:~# cd /code root@0d31cad7a539:/code# ./build/native_args_assembler -f udt.js -t 6a5f904a6f6ec270b6dde3add221aa8a82120e2e98ea6dac59160dd09359084201000000 ``` -------------------------------- ### Configure lib.rs for Native Simulator (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Sets up the `lib.rs` file to conditionally disable `no_std` when the `native-simulator` feature is enabled. It also conditionally includes and exports the `program_entry` function from a `main` module, allowing the simulator to call the script's entry point. ```Rust #![cfg_attr(not(feature = "native-simulator"), no_std)] #![allow(special_module_name)] #![allow(unused_attributes)] #[cfg(feature = "native-simulator")] mod main; #[cfg(feature = "native-simulator")] pub use main::program_entry; ``` -------------------------------- ### WABT C Wrapper for CKB - C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md This C code provides a wrapper for the WASM-to-C output generated by WABT. It includes necessary headers for CKB syscalls, defines an `env_abort` function, loads input data from the CKB witness, initializes the WASM module, calls the exported `fib` function, and returns the result. ```C #include #include #include "ckb_syscalls.h" #include "fib.h" void (*Z_envZ_abortZ_viiii)(u32, u32, u32, u32); void env_abort(u32 a, u32 b, u32 c, u32 d) { abort(); } int main() { uint32_t value; uint64_t len = 4; int ret = ckb_load_witness((void*) &value, &len, 0, 0, CKB_SOURCE_GROUP_INPUT); if (ret != CKB_SUCCESS) { return ret; } if (len < 4) { return -1; } init(); u8 result = Z_fibZ_ii(value); return result; } ``` -------------------------------- ### Implementing sUDT Script Entry Point and Validation (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/sudt-script.mdx This Rust function serves as the main entry point for the sUDT script. It first checks if the script is executing in owner mode, returning success immediately if true. Otherwise, it collects the total UDT amounts from input and output cells and validates that the output amount does not exceed the input amount, returning an error if the validation fails. ```Rust pub fn program_entry() -> i8 { ckb_std::debug!("This is a sample UDT contract!"); let script = load_script().unwrap(); let args: Bytes = script.args().unpack(); ckb_std::debug!("script args is {:?}", args); // Check if the script is in owner mode if check_owner_mode(&args) { return 0; // Success if in owner mode } // Collect amounts from input and output cells let inputs_amount: u128 = match collect_inputs_amount() { Ok(amount) => amount, Err(err) => return err as i8, }; let outputs_amount = match collect_outputs_amount() { Ok(amount) => amount, Err(err) => return err as i8, }; // Validate that inputs are greater than or equal to outputs if inputs_amount < outputs_amount { return Error::InvalidAmount as i8; // Error if invalid amount } 0 // Success } ``` -------------------------------- ### Rust Script Structure Definition Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/intro-to-script.mdx This Rust struct defines the fundamental structure of a Script in Nervos CKB. It includes fields for `code_hash` to identify the script code, `hash_type` to specify how the code is located, and `args` for script-specific parameters. ```Rust pub struct Script { pub code_hash: H256, pub hash_type: ScriptHashType, pub args: JsonBytes, } ``` -------------------------------- ### Create CKB Script Object from Data Hash (JavaScript) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-2.md Shows how to create a CKB script object (`carrotTypeScript`) in Lumos. It calculates the Blake2b hash of the deployed script data (`carrot`) using `lumos.utils.ckbHash`, sets the `hashType` to "data", and uses an empty string for `args` as the script doesn't require arguments. This object represents the script that can be referenced in a cell's `type` or `lock` script. ```js > const bytes = require("@ckb-lumos/lumos/codec").bytes; > const carrotDataHash = lumos.utils.ckbHash(bytes.bytify("0x" + data.toString("hex"))); > const carrotTypeScript = { codeHash: carrotDataHash, hashType: "data", args: "0x" }; ``` -------------------------------- ### Inspecting WebAssembly Imports with wasm2wat Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-4.md This snippet demonstrates using `wabt/bin/wasm2wat` and `grep` to inspect the imports required by a WebAssembly module generated with `wasm-bindgen`. It reveals imports from `__wbindgen_placeholder__` and `__wbindgen_anyref_xform__`, highlighting the dependency on `wasm-bindgen`'s specific binding environment functions. ```Shell $ wabt/bin/wasm2wat wasm_secp256k1_test.wasm -o secp.wat $ cat secp.wat | grep "(import" (import "__wbindgen_placeholder__" "__wbindgen_describe" (func $__wbindgen_describe (type 3))) (import "__wbindgen_anyref_xform__" "__wbindgen_anyref_table_grow" (func $__wbindgen_anyref_table_grow (type 4))) (import "__wbindgen_anyref_xform__" "__wbindgen_anyref_table_set_null" (func $__wbindgen_anyref_table_set_null (type 3))) ``` -------------------------------- ### Benchmarking Native C Binary (1 Iteration) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Runs the compiled native C benchmark binary (ckb-vm-bench-scripts/build/secp256k1_bench) using the runner.rb script with input 0x01010000. This input likely encodes the number of iterations (1) and the specific test case (0x01). The output shows the run result and cycle consumption. ```Shell ./runner.rb ckb-vm-bench-scripts/build/secp256k1_bench 0x01010000 ``` -------------------------------- ### Creating Transaction Using Deployed Script - Node.js Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-5.md This Node.js snippet, using @ckb-lumos/lumos, demonstrates how to create a transaction that utilizes the previously deployed duktape REPL script. It defines the script using the code hash of the deployed binary and the arguments generated by `native_args_assembler`. It then creates a transaction skeleton, transfers funds, sets the type script of an output cell to the duktape script, and adds the cell containing the deployed binary as a cell dependency. ```javascript > const duktapeReplCodeHash = lumos.utils.ckbHash(bytes.bytify("0x" + data.toString("hex"))); > const duktapeTypeScript = { codeHash: duktapeReplCodeHash, hashType: "data", args: "0x370000000c00000033000000000000001f000000434b422e6465627567282249276d2072756e6e696e6720696e204a5322290a04000000", }; > let txSkeleton = lumos.helpers.TransactionSkeleton({ cellProvider: indexer }); > txSkeleton = await lumos.commons.common.transfer(txSkeleton,[wallet.address],wallet2.address,"150" + "00000000"); > txSkeleton.update("outputs", (outputs) => { let cell = outputs.first(); cell.cellOutput.type = duktapeTypeScript; return outputs; }); > txSkeleton = lumos.helpers.addCellDep(txSkeleton, { outPoint: { txHash: duktapeReplTxHash, index: "0x0", }, depType: "code", }); ``` -------------------------------- ### Build wabt and Convert WASM to C Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-4.md Shell commands to clone the wabt repository, build it using CMake, and then use the wasm2c tool to convert the compiled fib.wasm file into C source code (fib.c). ```Shell git clone --recursive https://github.com/WebAssembly/wabt cd wabt mkdir build cd build cmake .. cmake --build . cd .. wabt/bin/wasm2c fib.wasm -o fib.c ``` -------------------------------- ### Make Runner Script Executable (Shell) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-9.md Grants execute permissions to the runner.rb script, which is used to automate running CKB scripts with the debugger. ```Shell chmod +x runner.rb ``` -------------------------------- ### Native Simulator Entry Functions (Rust) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/debug-script.mdx Displays the two C functions, `__ckb_std_main` and `__set_script_info`, exported by the `ckb-std::entry_simulator` macro. These functions serve as the entry point and state passing mechanism for the native simulator when debugging CKB scripts. ```Rust unsafe extern "C" fn __ckb_std_main( argc: core::ffi::c_int, // Arg is the same as *const c_char ABI wise. argv: *const $crate::env::Arg, ) -> i8 { ... } unsafe extern "C" fn __set_script_info( ptr: *mut core::ffi::c_void, tx_ctx_id: u64, proc_ctx_id: u64, ) { ... } ``` -------------------------------- ### Create Script Type Object from Deployed Data Hash Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script-course/intro-to-script-2.md This JavaScript snippet shows how to create the `carrotTypeScript` object required by CKB transactions. It calculates the Blake2b hash of the deployed script binary data using `lumos.utils.ckbHash` and the `@ckb-lumos/lumos/codec` bytes utility. The `hashType` is set to "data" to indicate the script is referenced by the hash of its data, and `args` is set to empty bytes as the script doesn't require arguments. ```js > const bytes = require("@ckb-lumos/lumos/codec").bytes; > const carrotDataHash = lumos.utils.ckbHash(bytes.bytify("0x" + data.toString("hex"))); > const carrotTypeScript = { codeHash: carrotDataHash, hashType: "data", args: "0x" }; ``` -------------------------------- ### Caller Script for Spawning Process (C) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/docs/script/syscalls-for-script.mdx This C code snippet demonstrates a CKB script acting as a 'caller'. It creates pipes to establish communication channels (mimicking stdin/stdout), spawns another script ('callee') inheriting these pipes, writes data to the callee's stdin, closes the write end, reads the echoed data from the callee's stdout, and verifies the received data. ```C #include #include #include "ckb_syscalls.h" #define CKB_STDIN (0) #define CKB_STDOUT (1) // Function read_all reads from fd until an error or EOF and returns the data it read. int ckb_read_all(uint64_t fd, void* buffer, size_t* length) { int err = 0; size_t read_length = 0; size_t full_length = *length; uint8_t* b = buffer; while (true) { size_t n = full_length - read_length; err = ckb_read(fd, b, &n); if (err == CKB_OTHER_END_CLOSED) { err = 0; *length = read_length; break; } else { if (err != 0) { goto exit; } } if (full_length - read_length == 0) { err = CKB_LENGTH_NOT_ENOUGH; if (err != 0) { goto exit; } } b += n; read_length += n; *length = read_length; } exit: return err; } // Mimic stdio fds on linux int create_std_fds(uint64_t* fds, uint64_t* inherited_fds) { int err = 0; uint64_t to_child[2] = {0}; uint64_t to_parent[2] = {0}; err = ckb_pipe(to_child); if (err != 0) { goto exit; } err = ckb_pipe(to_parent); if (err != 0) { goto exit; } inherited_fds[0] = to_child[0]; inherited_fds[1] = to_parent[1]; inherited_fds[2] = 0; fds[CKB_STDIN] = to_parent[0]; fds[CKB_STDOUT] = to_child[1]; exit: return err; } int main() { int err = 0; const char* argv[] = {}; uint64_t pid = 0; uint64_t fds[2] = {0}; // it must be end with zero uint64_t inherited_fds[3] = {0}; err = create_std_fds(fds, inherited_fds); if (err != 0) { goto exit; } spawn_args_t spgs = { .argc = 0, .argv = argv, .process_id = &pid, .inherited_fds = inherited_fds, }; err = ckb_spawn(0, 3, 0, 0, &spgs); if (err != 0) { goto exit; } size_t length = 0; length = 12; err = ckb_write(fds[CKB_STDOUT], "Hello World!", &length); if (err != 0) { goto exit; } err = ckb_close(fds[CKB_STDOUT]); if (err != 0) { goto exit; } uint8_t buffer[1024] = {0}; length = 1024; err = ckb_read_all(fds[CKB_STDIN], buffer, &length); if (err != 0) { goto exit; } err = memcmp("Hello World!", buffer, length); if (err != 0) { goto exit; } exit: return err; } ``` -------------------------------- ### Benchmarking Native C Binary (5 Iterations) Source: https://github.com/nervosnetwork/docs.nervos.org/blob/develop/website/blog/intro-to-script-8.md Runs the compiled native C benchmark binary (ckb-vm-bench-scripts/build/secp256k1_bench) using the runner.rb script with input 0x01050000. This input likely encodes the number of iterations (5) and the specific test case (0x01). The output shows the run result and cycle consumption. ```Shell ./runner.rb ckb-vm-bench-scripts/build/secp256k1_bench 0x01050000 ```