Skip to content

Getting Started

This guide walks you through installing the toolchain, creating a contract, building it reproducibly, and deploying it to a local Dilithia node.

Prerequisites

You need one of the following:

Install Rust via rustup if you don't already have it:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Add the WASM compilation target:

rustup target add wasm32-unknown-unknown

If you prefer not to install Rust locally, you can compile contracts inside the pre-built Docker image. See the Docker guide for details.

Required for Optimized Normal Builds: Install Binaryen

Binaryen provides wasm-opt, which the build command uses to optimize the compiled WASM binary. On Debian/Ubuntu:

sudo apt-get install binaryen

On macOS:

brew install binaryen

If wasm-opt is not installed, normal optimized builds fail. There is no silent fallback to an unoptimized artifact.

Install the CLI

Clone the repository and install:

git clone https://github.com/dilithia/contract-tools.git
cd contract-tools
cargo install --path cli

This installs the dilithia-contract binary into your Cargo bin directory (usually ~/.cargo/bin/).

Verify the installation:

dilithia-contract --version

Complete Walkthrough

1. Create a New Project

dilithia-contract init --name my_token
cd my_token

This scaffolds a new directory with:

  • Cargo.toml pinned for reproducible builds
  • Cargo.lock generated up front
  • rust-toolchain.toml pinned to the supported toolchain
  • vendored dilithia-sdk and macro crates
  • src/lib.rs with a starter contract exposing set, get, and del

2. Write Your Contract

Open src/lib.rs and edit the generated template. Here is what the starter contract looks like:

#![no_std]
extern crate alloc;

use dilithia_sdk::prelude::*;

#[contract]
mod my_token {
    use super::*;

    pub fn set(ctx: &mut Ctx, args: Value) -> Result<Value, String> {
        let key = args["key"].as_str().ok_or("missing key")?;
        let value = &args["value"];
        ctx.storage_set(key, value.clone());
        ctx.emit("set", json!({ "key": key }));
        Ok(json!({ "ok": true }))
    }

    pub fn get(ctx: &Ctx, args: Value) -> Result<Value, String> {
        let key = args["key"].as_str().ok_or("missing key")?;
        let value: Option<Value> = ctx.storage_get(key);
        Ok(json!({ "value": value }))
    }

    pub fn del(ctx: &mut Ctx, args: Value) -> Result<Value, String> {
        let key = args["key"].as_str().ok_or("missing key")?;
        ctx.storage_set(key, "");
        ctx.emit("del", json!({ "key": key }));
        Ok(json!({ "ok": true }))
    }
}

See Writing Contracts for a detailed guide on the contract API.

3. Build

dilithia-contract build

This runs cargo build --locked --target wasm32-unknown-unknown --release and requires wasm-opt to succeed when optimization is enabled. The compiled artifact is placed at:

target/wasm32-unknown-unknown/release/my_token.wasm

4. Deploy to a Local Node

Running a local node

You need a Dilithia node running locally. Examples below use http://localhost:8000/rpc.

Deploy the contract:

dilithia-contract deploy \
  --name my_token \
  --wasm target/wasm32-unknown-unknown/release/my_token.wasm \
  --rpc http://localhost:8000/rpc \
  --secret-key $DILITHIA_SECRET_KEY

Environment variable

You can set DILITHIA_SECRET_KEY in your shell environment to avoid passing --secret-key on every command.

5. Interact with the Contract

Set a value:

dilithia-contract call \
  --contract my_token \
  --method set \
  --args '{"key":"greeting","value":"hello"}' \
  --rpc http://localhost:8000/rpc \
  --secret-key $DILITHIA_SECRET_KEY \
  --wait

Read it back:

dilithia-contract query \
  --contract my_token \
  --method get \
  --args '{"key":"greeting"}' \
  --rpc http://localhost:8000/rpc

Next Steps