### Clone Developer Training Course Repository Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/lab-exercise-setup.md Use this command to clone the `developer-training-course` repository from GitHub. This repository contains all the example code and lab exercises necessary for the lessons. ```Bash git clone https://github.com/jordanmack/developer-training-course.git ``` -------------------------------- ### Navigate and Install Node.js Dependencies Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/lab-exercise-setup.md After cloning the repository, use these commands to navigate into the `developer-training-course` directory and install the required Node.js dependencies using `npm i`. Warnings during installation are common and usually harmless, but ensure Node.js v18 LTS is active if errors occur. ```Bash cd developer-training-course npm i ``` -------------------------------- ### Clone Developer Training Course Script Examples Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command clones the `developer-training-course-script-examples` GitHub repository, which contains example lock and type scripts for lessons. This is the first step to setting up the environment for further training. ```Bash git clone https://github.com/jordanmack/developer-training-course-script-examples.git ``` -------------------------------- ### Install Capsule using Cargo Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command installs the `ckb-capsule` tool globally using Rust's Cargo package manager. It requires Rust and Docker to be pre-installed and configured for proper functionality. ```Bash cargo install ckb-capsule ``` -------------------------------- ### Run Tests for Developer Training Course Scripts Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command executes all tests for the built script binaries using `capsule test`. Running tests verifies that the scripts have been built correctly and are functioning as expected, ensuring a proper setup for the lessons. ```Bash capsule test ``` -------------------------------- ### Rust Smart Contract Entry Point Logic (`entry.rs`) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This Rust code defines the main logic for a smart contract. It demonstrates how to import necessary libraries, load script arguments and transaction hash, and handle custom errors. The example checks if arguments are supplied and returns an error if they are empty, showcasing basic contract interaction and error handling. ```Rust // Import from `core` instead of from `std` since we are in no-std mode use core::result::Result; // Import heap related library from `alloc` // https://doc.rust-lang.org/alloc/index.html use alloc::{vec, vec::Vec}; // Import CKB syscalls and structures // https://docs.rs/ckb-std/ use ckb_std::{ debug, high_level::{load_script, load_tx_hash}, ckb_types::{bytes::Bytes, prelude::*}, }; use crate::error::Error; pub fn main() -> Result<(), Error> { // remove below examples and write your code here let script = load_script()?; let args: Bytes = script.args().unpack(); debug!("script args is {:?}", args); // return an error if args is invalid if args.is_empty() { return Err(Error::MyError); } let tx_hash = load_tx_hash()?; debug!("tx hash is {:?}", tx_hash); let _buf: Vec<_> = vec![0u8; 32]; Ok(()) } ``` -------------------------------- ### CKB CLI: Example Output for Get Live Cell Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/storing-data-in-a-cell.md This JSON output illustrates the expected response from the `ckb-cli rpc get_live_cell --with-data` command. It provides comprehensive details about the retrieved cell, including its data content, hash, output capacity, lock script, type script, and current status. ```json cell: data: content: 0x48656c6c6f204e6572766f7321 hash: 0xaa44a1b32b437a2a68537398f7730b4d3ef036cd1fdcf0e7b15a04633755ac31 output: capacity: 0x1b9130a00 lock: args: 0x988a9c3e74c09dab76c8e41d481a71f4d36d772f code_hash: 0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8 hash_type: type type: ~ status: live ``` -------------------------------- ### Execute CKB Command to List Devnet Hashes Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/lab-exercise-setup.md Run this command from your CKB Node directory to retrieve the system cell hashes of your devnet. These hashes, including `tx_hash` and `index` for various cell types like `SECP256K1_BLAKE160` and `DAO`, are necessary for configuring the `config.json` file in the developer training course repository. This configuration allows the Lumos framework to correctly identify and utilize devnet resources for transaction building. ```Shell ./ckb list-hashes ``` -------------------------------- ### Load Header Epoch Start Block Number (CKB High-Level API) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Retrieves the starting block number of the epoch from a transaction header using the CKB high-level Rust API. This is useful for understanding the block context of the current transaction. ```Rust ckb_std::high_level::load_header_epoch_start_block_number() ``` -------------------------------- ### JavaScript: Example CKB Lock Script Object Structure Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md This JavaScript object literal shows the typical structure of a CKB lock script after conversion from an address. It includes `codeHash` to identify the script's executable code, `hashType` to specify its interpretation, and `args` to pass dynamic data to the script upon execution. This structure defines the 'what' and 'how' of script execution. ```javascript { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', hashType: 'type', args: '0x988a9c3e74c09dab76c8e41d481a71f4d36d772f' } ``` -------------------------------- ### Example Output: ckb-cli get_live_cell Response Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/storing-data-in-a-cell.md This YAML-like structure represents the typical output from the `ckb-cli rpc get_live_cell` command. It details the cell's data content (hex-encoded), data hash, output capacity in Shannons, and lock/type scripts, confirming the successful storage and retrieval of data on the CKB blockchain. ```yaml cell: data: content: 0x48656c6c6f204e6572766f7321 hash: 0xaa44a1b32b437a2a68537398f7730b4d3ef036cd1fdcf0e7b15a04633755ac31 output: capacity: 0x1b9130a00 lock: args: 0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7 code_hash: 0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8 hash_type: type type: ~ status: live ``` -------------------------------- ### Example of Adding Input Capacity Cells (Commented Out) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/validating-a-transaction.md This commented-out code block provides an example of how additional capacity cells could be added to a CKB transaction. Although not utilized in this specific example, it demonstrates the typical pattern for collecting and concatenating input cells to meet transaction capacity requirements, such as covering transaction fees. ```javascript // Add input capacity cells. // const capacityRequired = ckbytesToShannons(61n) + txFee; // const collectedCells = await collectCapacity(indexer, addressToScript(address1), capacityRequired); // transaction = transaction.update("inputs", (i)=>i.concat(collectedCells.inputCells)); ``` -------------------------------- ### Creating CKB Cells with ICC Lock (JavaScript) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/untitled.md This snippet demonstrates how to generate a transaction to create two cells that utilize the ICC Lock. It details the setup of the lock script, including the `code_hash`, `hash_type`, and the `args` which specify the required CKBytes for unlocking (500 CKBytes in this case). The cells are created with a capacity of 500 CKBytes each. ```javascript // Create cells using the ICC Lock. const outputCapacity1 = ckbytesToShannons(500n); const iccLockAmount1 = intToU64LeHexBytes(ckbytesToShannons(500n)); const lockScript1 = { code_hash: dataFileHash1, hash_type: "data", args: iccLockAmount1 }; const output1 = {cell_output: {capacity: intToHex(outputCapacity1), lock: lockScript1, type: null}, data: "0x"}; transaction = transaction.update("outputs", (i)=>i.concat([output1, output1])); ``` -------------------------------- ### CKB CLI: Get Live Cell with Data Command Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/storing-data-in-a-cell.md This command-line instruction uses `ckb-cli` to retrieve the details of a live CKB cell, including its embedded data. It requires the transaction hash and the output index to pinpoint the specific cell for inspection. ```ckb-cli ckb-cli rpc get_live_cell --tx-hash --index 0 --with-data ``` -------------------------------- ### Lumos Cell Output JSON Structure Example Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/storing-data-in-a-cell.md This snippet illustrates the fundamental JSON structure used for defining a cell's output in Lumos. It includes fields for `capacity`, `lock` script, `type` script, and the `data` field, which holds the cell's content as a hex string. ```javascript { cellOutput: { capacity: outputCapacity, lock: addressToScript(address), type: null }, data: "0x" } ``` -------------------------------- ### Rust Enum for CKB Syscall Data Sources Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Defines the Source enum in Rust, which specifies the origin of data for CKB syscalls. This enum includes variants like Input, Output, CellDep, HeaderDep, GroupInput, and GroupOutput, guiding where transaction components are loaded from. ```Rust pub enum Source { Input, Output, CellDep, HeaderDep, GroupInput, GroupOutput, } ``` -------------------------------- ### Rust: Validate Create Operation for Counter Cell Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/operation-detection.md This function validates a 'create' (minting) operation for a counter cell. It loads the output cell data and ensures that its initial value is `0u64`, preventing creation with invalid starting values. ```Rust // Validate a transaction to create a counter cell. fn validate_create() -> Result<(), Error> { // Load the output cell data and verify that the value is 0u64. let cell_data = load_cell_data(0, Source::GroupOutput)?; if cell_data != 0u64.to_le_bytes().to_vec() { return Err(Error::InvalidOutputCellData); } Ok(()) } ``` -------------------------------- ### JavaScript: Lumos Transaction for Creating Aggregatable Counter Cells Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/creating-aggregatable-scripts.md This JavaScript code, part of a Lumos example, demonstrates how to programmatically create multiple cells that utilize the Aggregatable Counter type script. It iterates through a predefined set of initial amounts, converting each into a u64 LE hex byte format, and then constructs and adds new cell outputs to a transaction, each containing the Aggregatable Counter type script and its initial data. ```JavaScript // Create cells using the Aggregatable Counter type script. for(const amount of [0n, 42n, 9_000n]) { const outputCapacity1 = ckbytesToShannons(102n); const lockScript1 = addressToScript(address1); const typeScript1 = { codeHash: dataFileHash1, hashType: "data", args: "0x" }; const data1 = intToU64LeHexBytes(amount); const output1 = {cellOutput: {capacity: intToHex(outputCapacity1), lock: lockScript1, type: typeScript1}, data: data1}; transaction = transaction.update("outputs", (i)=>i.push(output1)); } ``` -------------------------------- ### Locating and Adding IC3Type Cells to Transaction Inputs Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/validating-a-transaction.md This code illustrates how to locate and add specific IC3Type cells to a CKB transaction's inputs using the Lumos framework's CellCollector class. It queries for live cells matching a defined lock script and type script, then adds a fixed number of these cells to the transaction. The example uses simplified logic, assuming a known number of cells were previously created. ```javascript // Add the IC3Type cells to the transaction. const lockScript1 = addressToScript(address1); const typeScript1 = { code_hash: dataFileHash1, hash_type: "data", args: "0x" }; const query = {lock: lockScript1, type: typeScript1}; const cellCollector = (new CellCollector(indexer, query)).collect(); for(let i = 0; i < 3; ++i) { const cell = (await cellCollector.next()).value; transaction = transaction.update("inputs", (i)=>i.push(cell)); } ``` -------------------------------- ### Build Developer Training Course Script Binaries Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md These commands navigate into the cloned `developer-training-course-script-examples` directory and then use `capsule build` to compile all the script binaries. This step is necessary to prepare the scripts for testing and deployment. ```Bash cd developer-training-course-script-examples capsule build ``` -------------------------------- ### Create a new Capsule project Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command initializes a new Capsule project named `myproject` in the current directory. It sets up the basic project structure, including configuration files, a README, and a default contract. ```Bash capsule new myproject ``` -------------------------------- ### Build a Capsule project Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command compiles the current Capsule project binaries in debug mode. It resolves and downloads necessary dependencies, then compiles the project's contracts into executable binaries. ```Bash capsule build ``` -------------------------------- ### Test a Capsule project Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command executes all tests defined for the Capsule project. It compiles necessary testing tools, including a light-weight simulator, and runs the compiled scripts in a simulated blockchain environment to verify functionality. ```Bash capsule test ``` -------------------------------- ### Output of `capsule new` command Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This shows the expected console output after successfully creating a new Capsule project. It lists the files and directories created and confirms the initialization of the Git repository and the default contract. ```Shell New project "myproject" Created file "capsule.toml" Created file "deployment.toml" Created file "README.md" Created file "Cargo.toml" Created file ".gitignore" Initialized empty Git repository in /home/username/myproject/.git/ Created "/home/username/myproject" Created tests Created library `tests` package New contract "myproject" Created binary (application) `myproject` package Rewrite Cargo.toml Rewrite ckb_capsule.toml Done ``` -------------------------------- ### Lumos: Initialize Configuration Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md Initializes the Lumos framework using a configuration file, typically `config.json`. This step is mandatory before performing any Lumos operations, ensuring the framework is set up with the correct network parameters. ```javascript // Initialize the Lumos configuration using ./config.json. initializeConfig(CONFIG); ``` -------------------------------- ### Rust SUDT Script Main Entry Point Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/creating-a-token.md The `main` function serves as the primary entry point for the SUDT script. It loads script arguments, checks if owner mode is enabled (exiting early if true), calculates input and output token amounts, and enforces the token scarcity rule (`input_token_amount >= output_token_amount`). The script returns success if all validations pass, or an error otherwise. ```rust // Main entry point. pub fn main() -> Result<(), Error> { // Load the currently executing script and get the args. let script = load_script()?; let args: Bytes = script.args().unpack(); // Check if the script is being run by the owner and immediately return success if true. if check_owner_mode(&args)? { return Ok(()); } // Count the number of tokens in the GroupInput and GroupOutput. let input_token_amount = determine_token_amount(Source::GroupInput)?; let output_token_amount = determine_token_amount(Source::GroupOutput)?; // If the amount of input tokens is less than the amount of output tokens, return an error. if input_token_amount < output_token_amount { return Err(Error::Amount); } // No errors were found during validation. Return success. Ok(()) } ``` -------------------------------- ### Clone Developer Training Course Script Labs Repository Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This command clones the GitHub repository containing the Developer Training Course Script Labs. These labs are designed to be used with Capsule and are essential for practical exercises within the course. There is no need to build the labs immediately after cloning. ```bash git clone https://github.com/jordanmack/developer-training-course-script-labs.git ``` -------------------------------- ### Verify CKB Indexer Functionality with Lumos (JavaScript) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/cell-management.md This Lumos JavaScript code snippet demonstrates how to verify that the CKB Indexer functionality is enabled and running correctly. It initializes the Lumos configuration, creates an instance of the `Indexer` class pointing to the CKB node's RPC URL, and then calls `indexer.tip()` to retrieve and display the most recent block tip, confirming successful communication with the Indexer. ```javascript import fs from "fs"; import {initializeConfig} from "@ckb-lumos/config-manager"; import {Indexer} from "@ckb-lumos/ckb-indexer"; const CONFIG = JSON.parse(fs.readFileSync("../config.json")); const NODE_URL = "http://127.0.0.1:8114/"; const INDEXER_URL = "http://127.00.1:8114/"; initializeConfig(CONFIG); const indexer = new Indexer(INDEXER_URL, NODE_URL); (async function() { console.log(await indexer.tip()); })(); ``` -------------------------------- ### Efficient Binary Packing of Lock Arguments Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/untitled-1.md This pseudo-code snippet demonstrates a more efficient method for handling multiple lock arguments by directly packing binary values without serialization overhead. It shows how to read specific byte offsets (e.g., `[0..8]` for 64-bit integers) from the `lock_args` field, which is common when argument sizes are fixed and known. ```javascript lock_args = load_lock_args(); capacity_required = integer_from_binary(lock_args[0..8]); count_required = integer_from_binary(lock_args[8..16]); ``` -------------------------------- ### Lumos Transaction: Import Dependencies Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md This snippet imports necessary modules for Lumos-based CKB transaction development. It includes core Lumos components for configuration, address conversion, transaction handling, and indexing, along with custom utility and lab-specific functions. ```javascript import fs from "fs"; import {initializeConfig} from "@ckb-lumos/config-manager"; import {addressToScript, TransactionSkeleton} from "@ckb-lumos/helpers"; import {Indexer} from "@ckb-lumos/ckb-indexer"; import {addDefaultCellDeps, addDefaultWitnessPlaceholders, getLiveCell, sendTransaction, signTransaction, waitForTransactionConfirmation} from "../lib/index.js"; import {hexToInt, intToHex} from "../lib/util.js"; import {describeTransaction} from "./lab.js"; const CONFIG = JSON.parse(fs.readFileSync("../config.json")); ``` -------------------------------- ### Output of `capsule build` command Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This shows the expected console output during the build process of a Capsule project. It indicates dependency resolution, compilation steps for various crates, and the final successful build message. ```Shell Building contract myproject Updating crates.io index Downloading crates ... Downloaded cstr_core v0.2.6 Downloaded ckb-std v0.10.0 Compiling memchr v2.5.0 Compiling cfg-if v1.0.0 Compiling cc v1.0.73 Compiling cty v0.2.2 Compiling buddy-alloc v0.4.1 Compiling molecule v0.7.3 Compiling ckb-standalone-types v0.1.2 Compiling cstr_core v0.2.6 Compiling ckb-std v0.10.0 Compiling myproject v0.1.0 (/code/contracts/myproject) Finished dev [unoptimized + debuginfo] target(s) in 57.43s Done ``` -------------------------------- ### Creating CKB Cells with Hash Lock Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/using-the-witness.md This code demonstrates how to create CKB cells using a Hash Lock. It sets up the lock script by including a Blake2b hash of the secret preimage in the `args` field. Two cells are created with this hash lock, making the hash visible on-chain while keeping the preimage secret and required for unlocking. ```javascript const outputCapacity1 = ckbytesToShannons(500n); const lockScript1 = { code_hash: dataFileHash1, hash_type: "data", args: blake2b(32).update(preimage).digest("hex") }; const output1 = {cell_output: {capacity: intToHex(outputCapacity1), lock: lockScript1, type: null}, data: "0x"}; transaction = transaction.update("outputs", (i)=>i.concat([output1, output1])); ``` -------------------------------- ### Lumos Transaction: Define Configuration Constants Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md This snippet defines essential constants for interacting with the CKB Dev Blockchain and signing transactions. It includes URLs for the node and indexer, a private key and corresponding address, a placeholder for a previous transaction output, and the transaction fee in Shannons. ```javascript const NODE_URL = "http://127.0.0.1:8114/"; const INDEXER_URL = "http://127.0.0.1:8116/"; const PRIVATE_KEY = "0xd00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc"; const ADDRESS = "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqwgx292hnvmn68xf779vmzrshpmm6epn4c0cgwga"; const PREVIOUS_OUTPUT = { txHash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: "0x0" }; const TX_FEE = 100_000n; ``` -------------------------------- ### Conceptual Lock Script Signature Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/untitled-1.md This pseudo-code snippet illustrates a simplified conceptual signature for a lock script, showing how `args` and `input_cells` are passed. In reality, data is obtained via system calls, but this representation aids initial understanding of data flow. ```javascript function lockScript(args, input_cells) ``` -------------------------------- ### Creating Cells with OCC Lock in JavaScript Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/untitled-1.md This JavaScript snippet demonstrates how to create cells using the OCC Lock mechanism. It defines the output capacity, the required unlock amount, and the minimum number of matching output cells. The script then constructs the lock script with a data hash and packed arguments, finally adding two identical output cells to a transaction. ```javascript // Create cells using the OCC Lock. const outputCapacity1 = ckbytesToShannons(500n); const occLockAmount1 = intToU64LeHexBytes(ckbytesToShannons(1_000n)); const occLockCount1 = intToU64LeHexBytes(3); const lockScript1 = { code_hash: dataFileHash1, hash_type: "data", args: occLockAmount1 + occLockCount1.substr(2) }; const output1 = {cell_output: {capacity: intToHex(outputCapacity1), lock: lockScript1, type: null}, data: "0x"}; transaction = transaction.update("outputs", (i)=>i.concat([output1, output1])); ``` -------------------------------- ### Lumos: Create Cell with Always Success Binary Data Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md This JavaScript code snippet reads a binary file into a hex string, calculates the required capacity, and constructs an output cell for a Lumos transaction. This cell contains the always success binary data, preparing it for deployment on-chain. ```javascript // Create a cell with data from the specified file. const {hexString: hexString1, dataSize: dataSize1} = await readFileToHexString(dataFile1); const outputCapacity1 = ckbytesToShannons(61n) + ckbytesToShannons(dataSize1); const output1 = {cellOutput: {capacity: intToHex(outputCapacity1), lock: addressToScript(address1), type: null}, data: hexString1}; transaction = transaction.update("outputs", (i)=>i.push(output1)); ``` -------------------------------- ### Output of `capsule test` command Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/introduction-to-capsule.md This shows the expected console output after running tests for a Capsule project. It details the test compilation, execution of unit tests, and the final test results, indicating success or failure. ```Shell Finished test [unoptimized + debuginfo] target(s) in 1m 12s Running unittests src/lib.rs (target/debug/deps/tests-eb0bb2889f396ebc) running 2 tests [contract debug] script args is Bytes([]) test tests::test_empty_args ... ok [contract debug] script args is Bytes([42]) [contract debug] tx hash is [190, 153, 144, 72, 54, 166, 192, 113, 110, 225, 123, 15, 89, 128, 80, 36, 182, 213, 40, 188, 238, 250, 137, 35, 188, 180, 199, 13, 87, 148, 207, 39] consume cycles: 215704 test tests::test_success ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.32s Doc-tests tests running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` -------------------------------- ### Manage Transaction Inputs, Outputs, and Change Cells (JavaScript) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md This comprehensive snippet demonstrates how to manage inputs and outputs for a CKB transaction. It adds the 'always success' cell as an input, collects additional capacity cells to meet requirements, calculates total input and output capacities, and finally creates a change cell to return remaining CKBytes to the sender's default lock script. ```javascript // Add the always success cell to the transaction. const input = await getLiveCell(nodeUrl, alwaysSuccessCellOutPoint); transaction = transaction.update("inputs", (i)=>i.push(input)); // Add input capacity cells. const capacityRequired = ckbytesToShannons(61n) + txFee; const collectedCells = await collectCapacity(indexer, addressToScript(address1), capacityRequired); transaction = transaction.update("inputs", (i)=>i.concat(collectedCells.inputCells)); // Determine the capacity from all input Cells. const inputCapacity = transaction.inputs.toArray().reduce((a, c)=>a+hexToInt(c.cellOutput.capacity), 0n); const outputCapacity = transaction.outputs.toArray().reduce((a, c)=>a+hexToInt(c.cellOutput.capacity), 0n); // Create a change Cell for the remaining CKBytes. const changeCapacity = intToHex(inputCapacity - outputCapacity - txFee); let change = {cellOutput: {capacity: changeCapacity, lock: addressToScript(address1), type: null}, data: "0x"}; transaction = transaction.update("outputs", (i)=>i.push(change)); ``` -------------------------------- ### Lumos Transaction: Create Skeleton Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md Creates an empty transaction skeleton using Lumos's `TransactionSkeleton()` function. This skeleton serves as the base structure that will be progressively populated with inputs, outputs, and other transaction details before being signed and broadcast. ```javascript // Create a transaction skeleton. let transaction = TransactionSkeleton(); ``` -------------------------------- ### Retrieve CKB Transaction Details using ckb-cli Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/examining-a-transaction.md This command demonstrates how to use `ckb-cli` to fetch the complete details of a specific transaction. Users need to replace `` with the actual transaction hash obtained from a previous lab exercise. The output will include various transaction components, with a focus on inputs and outputs. ```shell rpc get_transaction --hash ``` -------------------------------- ### Execute JavaScript Code and Capture CKB Transaction Details Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md Execute the `index.js` script using Node.js to initiate a CKB transaction. The output displays the transaction's inputs, outputs, and the generated transaction hash. It is crucial to record this hash for subsequent steps, such as checking the transaction's confirmation status. ```javascript $ node index.js Inputs: - capacity: 1,713,808,107,881,380 Shannons lock: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947 type: null out_point: 0x0017950609aa557433a117eab807361fe3e21794f08fd29fa201fb005928bb3e-0x0 Outputs: - capacity: 1,713,808,107,781,380 Shannons lock: 0x32e555f3ff8e135cece1351a6a2971518392c1e30375c1e006ad0ce8eac07947 type: null Transaction Sent: 0xbdf6c1cbf69e97234aae29b6db4a1df107240cb478ff290c214d403b1dfbd94d ``` -------------------------------- ### Collecting CKB Hash Lock Cells for Consumption Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/using-the-witness.md This snippet illustrates how to collect previously created Hash Lock cells for consumption. It utilizes the `collectCapacity()` library function, specifying the exact same lock script used during cell creation to ensure the correct cells are retrieved. The required capacity is set to pull in the two 500 CKByte cells. ```javascript const capacityRequired1 = ckbytesToShannons(1_000n); const lockScript1 = { code_hash: dataFileHash1, hash_type: "data", args: blake2b(32).update(preimage).digest("hex") }; const collectedCells = await collectCapacity(indexer, lockScript1, capacityRequired1); transaction = transaction.update("inputs", (i)=>i.concat(collectedCells.inputCells)); ``` -------------------------------- ### Load Transaction Input (CKB API) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Loads a transaction input from the current transaction. This function is available across high-level Rust APIs, Rust syscall wrappers, and raw CKB VM syscalls, providing flexibility for different development needs. ```Rust ckb_std::high_level::load_input() ``` ```Rust ckb_std::syscalls::load_input() ``` ```C ckb_load_input() ``` -------------------------------- ### Enable CKB Indexer Module in ckb.toml Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/cell-management.md To activate the Indexer functionality within the CKB node, developers must add "Indexer" to the `modules` array in their `ckb.toml` configuration file. After modifying the file, the CKB node needs to be restarted for the changes to take effect, allowing the node to monitor and organize cell information for faster querying. ```toml # List of API modules: ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment", "Debug", "Indexer"] modules = ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment", "Debug", "Indexer"]ml ``` -------------------------------- ### Transfer CKBytes using CKB-CLI Wallet Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/sending-a-transaction.md Execute a CKByte transfer between two accounts using the `wallet transfer` command in `ckb-cli`. This command requires specifying the source account (`--from-account`), the destination address (`--to-address`), and the amount of CKBytes to send (`--capacity`). After execution, the tool prompts for a password and returns a transaction ID upon success. ```Shell wallet transfer --from-account ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqwgx292hnvmn68xf779vmzrshpmm6epn4c0cgwga --to-address ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq28phxutezqvjgfv5q38gn5kwek4m9km3cmajeqs --capacity 1000 ``` -------------------------------- ### JavaScript Pseudo-code for Blake2b Hash Lock Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/using-the-witness.md This JavaScript pseudo-code demonstrates a 'Hash Lock' mechanism. It loads a 32-byte Blake2b hash from the lock script arguments and a preimage from the witness group. The function then computes the Blake2b hash of the provided preimage and compares it against the stored hash. If they match, the cell is unlocked (returns 0); otherwise, it returns an error (returns 1). This specific lock should only be used in test environments due to security vulnerabilities. ```javascript function main() { lock_args = load_lock_args(); hash = lock_args[0..32]; witnessGroup = load_witness_group(); preimage = witnessGroup[0]; if(hash == blake2b(preimage))) { return 0; } return 1; } ``` -------------------------------- ### CKB-STD Load Functions API Reference Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Documents the CKB-STD functions for loading transaction data, including load_transaction, load_tx_hash, load_witness, and load_witness_args. It outlines their availability across high-level Rust APIs, direct syscalls, and RFC specifications. ```APIDOC Function: load_transaction() Contexts: - ckb_std::high_level::load_transaction() - ckb_std::syscalls::load_transaction() - ckb_load_transaction() (RFC-0009) Function: load_tx_hash() Contexts: - ckb_std::high_level::load_tx_hash() - ckb_std::syscalls::load_tx_hash() - ckb_load_tx_hash() (RFC-0009) Function: load_witness() Contexts: - ckb_std::syscalls::load_witness() - ckb_load_witness() (RFC-0009) Function: load_witness_args() Contexts: - ckb_std::high_level::load_witness_args() ``` -------------------------------- ### Load Transaction Script (CKB API) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Loads the current transaction's script. This function is available across high-level Rust APIs, Rust syscall wrappers, and raw CKB VM syscalls, enabling access to the script code itself. ```Rust ckb_std::high_level::load_script() ``` ```Rust ckb_std::syscalls::load_script() ``` ```C ckb_load_script() ``` -------------------------------- ### Add Witness Placeholders to CKB Transaction (JavaScript) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md This snippet adds default witness placeholders to the transaction. The witness section contains data, including signatures, that validate the transaction's inputs, and addDefaultWitnessPlaceholders() simplifies the creation of this required structure for common use cases. ```javascript // Add in the witness placeholders. transaction = addDefaultWitnessPlaceholders(transaction); ``` -------------------------------- ### Adjust CKB Transaction Capacity by Adding More Inputs Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/untitled-1.md This snippet calculates the current input and output capacities of the transaction and then adds additional capacity to balance the transaction. It uses `collectCapacity()` to find and include more cells from `address1` to cover the deficit and transaction fees. ```javascript // Determine the capacity from input and output cells. let inputCapacity = transaction.inputs.toArray().reduce((a, c)=>a+hexToInt(c.cell_output.capacity), 0n); let outputCapacity = transaction.outputs.toArray().reduce((a, c)=>a+hexToInt(c.cell_output.capacity), 0n); // Add capacity to the transaction. const capacityRequired2 = outputCapacity - inputCapacity + ckbytesToShannons(61n) + txFee; const {inputCells} = await collectCapacity(indexer, addressToScript(address1), capacityRequired2); transaction = transaction.update("inputs", (i)=>i.concat(inputCells)); ``` -------------------------------- ### CKB Script Hash Type Definitions Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md Defines the `hashType` values used in CKB lock and type scripts to interpret the `codeHash`, specifying how the script code should be matched and which CKB-VM version to use. These types determine whether the `codeHash` refers to the binary executable's data hash or a type script's hash, enabling different execution behaviors and upgradeability. ```APIDOC Hash Type: data Matching: Match code by data hash. CKB-VM Version: 0 Hash Type: type Matching: Match code by type hash. CKB-VM Version: 1 (always newest) Hash Type: data1 Matching: Match code by data hash. CKB-VM Version: 1 ``` -------------------------------- ### Load Transaction Input by Field (CKB API) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Loads a specific field from a transaction input. This function is available through Rust syscall wrappers and raw CKB VM syscalls, allowing granular access to input data. ```Rust ckb_std::syscalls::load_input_by_field() ``` ```C ckb_load_input_by_field() ``` -------------------------------- ### CKB-VM Syscall: debug() Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Provides debugging capabilities within CKB-VM scripts. This function is a direct syscall without a high-level CKB-STD equivalent. ```APIDOC Function: debug CKB-STD High-Level: N/A CKB-STD Syscall: debug() Syscall RFC: ckb_debug() ``` -------------------------------- ### Define Function to Add Default Cell Dependencies (JavaScript) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md This JavaScript function, `addDefaultCellDeps`, updates a transaction by pushing a default lock script cell dependency. It utilizes the `locateCellDep` function from Lumos to find well-known cell dependencies based on a `codeHash` and `hashType`. ```javascript function addDefaultCellDeps(transaction) { return transaction.update("cellDeps", (cellDeps)=>cellDeps.push(locateCellDep({codeHash: DEFAULT_LOCK_HASH, hashType: "type"}))); } ``` -------------------------------- ### Pseudo-code for DataCap Type Script Data Size Validation Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-script-args.md This pseudo-code outlines the fundamental logic for a type script that enforces a maximum data size on output cells. It demonstrates loading a size limit from arguments, iterating through output cells, and returning an error if any cell's data exceeds the specified limit. ```javascript function main() { max_data_size = integer_from_binary(args); outputGroup = load_output_group(); for cell in outputGroup { if(cell.data.length() > max_data_size) { return 1; } } return 0; } ``` -------------------------------- ### Verify CKB Transaction Confirmation Status with ckb-cli Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md Use the `ckb-cli` command-line utility to check the current status of a CKB transaction. Replace `` with the actual transaction hash obtained from the previous step. The transaction is considered confirmed once the output displays `status: committed`. ```bash rpc get_transaction --hash ``` -------------------------------- ### Rust: Main Entry Point for Transaction Mode Detection Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/operation-detection.md This `main` function serves as the primary entry point for the application, determining the transaction mode (Burn, Create, Transfer) and delegating to specific validation functions or returning immediately for burn operations and errors. ```Rust // Main entry point. pub fn main() -> Result<(), Error> { // Determine the mode and validate as needed. match determine_mode() { Ok(Mode::Burn) => return Ok(()), Ok(Mode::Create) => validate_create()?, Ok(Mode::Transfer) => validate_transfer()?, Err(e) => return Err(e), } Ok(()) } ``` -------------------------------- ### Print CKB Transaction Details (JavaScript) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/introduction-to-lumos.md This code prints the current transaction object to the console in a human-readable format. The describeTransaction() function, part of a shared library, simplifies debugging by presenting relevant transaction details without extraneous information. ```javascript // Print the details of the transaction to the console. describeTransaction(transaction.toJS()); ``` -------------------------------- ### Load Block Header - CKB API Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md This function is used to load the header of a CKB block. Block headers contain essential metadata about a block, such as its hash, parent hash, timestamp, and difficulty target. ```Rust load_header() Source: https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/high_level/fn.load_header.html ``` ```Rust load_header() Source: https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/syscalls/fn.load_header.html ``` ```APIDOC ckb_load_header() Source: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0009-vm-syscalls/0009-vm-syscalls.md#load-header ``` -------------------------------- ### CKB-VM Syscall: load_cell_code() Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Loads cell data as executable code. This function is a direct syscall without a high-level CKB-STD equivalent. ```APIDOC Function: load_cell_code CKB-STD High-Level: N/A CKB-STD Syscall: load_cell_code() Syscall RFC: ckb_load_cell_data_as_code() ``` -------------------------------- ### Load Input Out Point (CKB High-Level API) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Retrieves the out point of a transaction input using the CKB high-level Rust API. The out point identifies the previous transaction output consumed by this input. ```Rust ckb_std::high_level::load_input_out_point() ``` -------------------------------- ### Load Transaction Script Hash (CKB API) Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/syscalls.md Loads the hash of the current transaction's script. This function is available across high-level Rust APIs, Rust syscall wrappers, and raw CKB VM syscalls, useful for script identification and verification. ```Rust ckb_std::high_level::load_script_hash() ``` ```Rust ckb_std::syscalls::load_script_hash() ``` ```C ckb_load_script_hash() ``` -------------------------------- ### List Accounts in CKB-CLI Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/sending-a-transaction.md Use the `account list` command in `ckb-cli` to display all accounts managed by the tool. This is crucial for verifying the special dev blockchain accounts, which are pre-funded with a large amount of CKBytes for development purposes. The output also introduces Nervos CKB addresses, which are unique identifiers for transaction sources or destinations. ```Shell account list ``` -------------------------------- ### Rust ODCounter Main Entry Point Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/operation-detection.md This `main` function serves as the primary entry point for the ODCounter script. It orchestrates the script's execution by first determining the operational mode, then performing mode-specific validation, and finally returning either success or an error based on the outcome of these steps. ```rust // Main entry point. pub fn main() -> Result<(), Error> { // Determine the mode and validate as needed. match determine_mode() { Ok(Mode::Burn) => return Ok(()), Ok(Mode::Create) => validate_create()?, Ok(Mode::Transfer) => validate_transfer()?, Err(e) => return Err(e), } Ok(()) } ``` -------------------------------- ### Add Witnesses and Sign CKB Transaction Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/managing-permissions/untitled-1.md This final step adds necessary witness placeholders to the transaction and then signs it using the provided private key. Signatures are required because additional input cells using the default lock script were added, even though the OCC Lock itself doesn't require them. ```javascript // Add in the witness placeholders. transaction = addDefaultWitnessPlaceholders(transaction); // Sign the transaction. const signedTx = signTransaction(transaction, privateKey1); ``` -------------------------------- ### JavaScript: Always Success CKB Script Logic Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md This JavaScript pseudo-code illustrates the 'always success' script, a fundamental concept for CKB script development and testing. The script's sole purpose is to return `0`, signaling successful execution regardless of input. This simplifies testing by bypassing complex lock script requirements, allowing developers to focus on other script logic. ```javascript function script() { return 0; } ``` -------------------------------- ### Verify File Hash with ckb-cli Blake2b Utility Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/transactions/storing-data-in-a-cell.md This command calculates the Blake2b hash of a local file. It is used to verify that the hash of the stored data on the CKB blockchain, obtained from `get_live_cell`, matches the hash of the original file, thereby ensuring data integrity and authenticity. ```bash ckb-cli util blake2b --binary-path "./files/HelloNervos.txt" ``` -------------------------------- ### Rust SUDT Script Imports Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/creating-a-token.md This block imports necessary modules from `core` (for no-std environment) and `ckb_std` for CKB syscalls and structures, along with local error definitions. These imports are essential for the SUDT script's operation within the CKB environment. ```rust // Import from core instead of from std since we are in no-std mode. use core::result::Result; // Import CKB syscalls and structures. // https://nervosnetwork.github.io/ckb-std/riscv64imac-unknown-none-elf/doc/ckb_std/index.html use ckb_std::ckb_constants::Source; use ckb_std::ckb_types::{bytes::Bytes, prelude::*}; use ckb_std::high_level::{load_script, load_cell_lock_hash, load_cell_data, QueryIter}; // Import our local error codes. use crate::error::Error; ``` -------------------------------- ### Sign Transaction with JavaScript Source: https://github.com/jordanmack/developer-training-course-documentation/blob/master/scripting-basics/using-scripts.md This snippet demonstrates how to sign a transaction using a private key. While 'always success' locks do not require signing, this step is crucial when additional input cells with default locks (e.g., from address1) are included, as they mandate a standard signature for unlocking. ```javascript // Sign the transaction. const signedTx = signTransaction(transaction, privateKey1); ```