Docs Examples Whitepaper Explorer GitHub →
Tutorials

Learn by building

Step-by-step guides from your first node to deploying smart contracts on the quantum-resistant blockchain.

First Node First Transaction Become a Validator Multi-Node Network Custom Genesis REST API Unstake Tokens Docker Setup Block Explorer Deploy Contract Call Contract

1 Run Your First Node

Build CURS3D from source and start a local devnet node in under 2 minutes.

terminal
# Clone the repository
git clone https://github.com/Pazificateur69/curs3d.git
cd curs3d

# Build in release mode
cargo build --release

# Create a wallet (you'll be prompted for a password)
./target/release/curs3d wallet --output my_wallet.json

# Start the node
./target/release/curs3d node --validator-wallet my_wallet.json

# You should see:
# [+] Chain: curs3d-devnet | RPC: 127.0.0.1:9545 | HTTP API: :8080
# [+] Gossipsub active. mDNS discovery enabled.

The node starts with the TCP RPC on port 9545 (for CLI commands) and the HTTP REST API on port 8080 (for browsers and apps). Gossipsub and mDNS discovery activate automatically.

2 Send Your First Transaction

Transfer CUR tokens between two wallets using the CLI.

terminal
# Create a second wallet
./target/release/curs3d wallet --output recipient.json

# Check the recipient's address
./target/release/curs3d info --wallet recipient.json
# Output: CUR7f3a1b2c...9c2d

# Send 100 CUR from your wallet to the recipient
./target/release/curs3d send \
  --wallet my_wallet.json \
  --to CUR7f3a1b2c...9c2d \
  --amount 100 \
  --fee 1000

# Verify the transfer via REST API
curl http://localhost:8080/api/account/CUR7f3a1b2c...9c2d

The fee is specified in microtokens (1000 microtokens = 0.001 CUR). The transaction is broadcast to the network and included in the next block.

3 Become a Validator

Stake CUR tokens to register as a validator and start producing blocks.

terminal
# Stake 1000 CUR (the minimum stake)
./target/release/curs3d stake \
  --wallet my_wallet.json \
  --amount 1000 \
  --fee 1000

# Verify your validator status
curl http://localhost:8080/api/validators

# You'll appear in the active validator set at the next epoch
# Epochs are 32 blocks by default

# Check the current epoch
curl http://localhost:8080/api/status | jq '.data.epoch'

Your validator becomes active at the next epoch boundary. The minimum stake is 1,000 CUR (1,000,000,000 microtokens). Validators are selected to propose blocks with stake-weighted deterministic selection from the epoch snapshot.

4 Multi-Node Network

Run a local multi-node network using bootnodes for peer discovery.

terminal
# Terminal 1: Start the first node
./target/release/curs3d node \
  --port 4337 \
  --data-dir node1_data \
  --validator-wallet wallet1.json \
  --rpc-addr 127.0.0.1:9545

# Terminal 2: Start the second node connecting to the first
./target/release/curs3d node \
  --port 4338 \
  --data-dir node2_data \
  --validator-wallet wallet2.json \
  --rpc-addr 127.0.0.1:9546 \
  --bootnode /ip4/127.0.0.1/tcp/4337

# Nodes discover each other and begin syncing
# They exchange HeightAnnounce messages every 30 seconds

With mDNS enabled, nodes on the same local network discover each other automatically. Bootnodes are useful for connecting nodes across different networks. Each node needs a unique port, data directory, and RPC address.

5 Custom Genesis Configuration

Configure the chain parameters and pre-allocate balances at genesis.

genesis.json
{
  "chain_id": "my-testnet",
  "chain_name": "My Custom Testnet",
  "block_reward": 100000000,
  "minimum_stake": 500000000,
  "epoch_length": 16,
  "jail_duration_blocks": 32,
  "unstake_delay_blocks": 5,
  "block_gas_limit": 20000000,
  "initial_base_fee_per_gas": 1,
  "base_fee_change_denominator": 8,
  "allocations": [
    {
      "public_key": "<your_hex_pubkey>",
      "balance": 1000000000000,
      "staked_balance": 500000000
    }
  ],
  "upgrades": [
    {
      "height": 500,
      "version": 2,
      "description": "Enable advanced features"
    }
  ]
}
terminal
# Start a node with custom genesis
./target/release/curs3d node \
  --validator-wallet my_wallet.json \
  --genesis-config genesis.json

All genesis parameters have sensible defaults. Get your public key hex from curs3d info --wallet my_wallet.json. Protocol upgrades activate automatically at the specified block heights.

6 Using the REST API

Query the blockchain using curl or any HTTP client.

terminal
# Chain status
curl http://localhost:8080/api/status | jq

# Latest blocks (most recent 20)
curl "http://localhost:8080/api/blocks?limit=20" | jq

# Specific block by height
curl http://localhost:8080/api/block/0 | jq

# Account balance
curl http://localhost:8080/api/account/CUR7f3a...9c2d | jq

# Pending transactions
curl http://localhost:8080/api/pending | jq

# Active validators
curl http://localhost:8080/api/validators | jq

# Submit a transaction (with optional auth token)
curl -X POST http://localhost:8080/api/tx/submit \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_token" \
  -d '{"chain_id":"curs3d-devnet","kind":"Transfer",...}'

# All responses: {"ok": true, "data": {...}}

The REST API on port 8080 has full CORS support. The optional Authorization header enables token-gated access to write endpoints. Max body size: 1 MB.

7 Unstake Tokens

Withdraw your staked CUR tokens after the unstake delay period.

terminal
# Check your current stake
curl http://localhost:8080/api/account/CURyour_address | jq '.data.staked_balance'

# Submit an Unstake transaction via the REST API
# The unstake delay is 10 blocks by default

# Monitor the chain height to wait for delay
curl http://localhost:8080/api/status | jq '.data.height'

# After the delay, your tokens return to your balance
curl http://localhost:8080/api/account/CURyour_address | jq '.data.balance'

The unstake delay protects the network from sudden validator exits. During the delay, your stake cannot be withdrawn. The delay is configurable in genesis (default: 10 blocks).

8 Docker Setup

Run CURS3D in Docker with a pre-configured 2-node network.

terminal
# Build the Docker image (multi-stage build)
docker build -t curs3d .

# Run a 2-node network with docker-compose
docker-compose up

# Node 1 API: http://localhost:8080
# Node 2 API: http://localhost:8081

# Or run a single node
docker run -p 4337:4337 -p 8080:8080 -p 9545:9545 curs3d \
  curs3d node --validator-wallet /data/wallet.json

# Check the chain is running
curl http://localhost:8080/api/status

The multi-stage Docker build produces a minimal image. The docker-compose configuration creates wallets and starts both nodes with mDNS discovery enabled.

9 Block Explorer

Use the built-in web-based block explorer to browse the chain.

terminal
# Start a node first
./target/release/curs3d node --validator-wallet my_wallet.json

# Serve the website (in another terminal)
cd website && python3 -m http.server 3000

# Open: http://localhost:3000/explorer.html
# The explorer connects to http://localhost:8080 by default
# You can change the API URL in the configuration bar

The block explorer connects to the REST API and displays blocks, transactions, account balances, and chain status in real time via Server-Sent Events.

10 Deploy a Smart Contract

Deploy a WebAssembly smart contract to the CURS3D blockchain.

terminal
# 1. Write your contract in Rust (wasm32-unknown-unknown)
# 2. Compile to WASM
cargo build --target wasm32-unknown-unknown --release

# 3. Hex-encode the WASM bytecode
xxd -p target/wasm32-unknown-unknown/release/contract.wasm | tr -d '\n'

# 4. Submit a DeployContract transaction
curl -X POST http://localhost:8080/api/tx/submit \
  -H "Content-Type: application/json" \
  -d '{
    "chain_id": "curs3d-devnet",
    "kind": "DeployContract",
    "from": [...],
    "sender_public_key": [...],
    "to": [],
    "amount": 0,
    "fee": 1000,
    "nonce": 1,
    "gas_limit": 500000,
    "data": "<hex_wasm_bytecode>",
    "timestamp": 1234567890,
    "signature": {...}
  }'

# Gas: 21,000 (base) + 32,000 (deploy) + 16/byte
# Receipt: {"status":"Success","gas_used":53216,...}

The WASM VM validates bytecode, meters gas per instruction, and stores the contract on-chain. The contract address is derived from deployer address + nonce.

11 Call a Smart Contract

Invoke a function on a deployed contract using CallContract.

terminal
# Call a deployed contract
curl -X POST http://localhost:8080/api/tx/submit \
  -H "Content-Type: application/json" \
  -d '{
    "chain_id": "curs3d-devnet",
    "kind": "CallContract",
    "from": [...],
    "sender_public_key": [...],
    "to": [<contract_address_bytes>],
    "amount": 0,
    "fee": 1000,
    "nonce": 2,
    "gas_limit": 200000,
    "data": "<function_selector_and_args>",
    "timestamp": 1234567890,
    "signature": {...}
  }'

# Host functions available to contracts:
#   storage_read   -- 200 gas
#   storage_write  -- 5,000 gas
#   emit_log       -- 375 gas
#   get_caller / get_input / set_return

# Receipt: {"status":"Success","gas_used":45832,"logs":[...]}

Each contract has isolated key-value storage. The block gas limit (10,000,000) is enforced -- transactions exceeding the remaining gas budget are deferred. All storage changes are reflected in the state root.