Rivellum

Rivellum Portal

Download Wallet (Chrome)
Checking...
mainnet

Developer Getting Started Guide

Welcome to Rivellum development! This guide will help you set up your environment, run a local node, and build your first intent-based application.

šŸ”— API Reference: Explore all available endpoints interactively in the API Explorer with live testing and code examples.

Prerequisites

Required Software

  • Rust: 1.81+ with cargo

    rustup default stable
    rustup update
    
  • Node.js: 20+ with npm

    node --version  # Should be v20+
    npm --version
    
  • Git: For cloning the repository

Optional Tools

  • Docker: For running local devnets
  • mistc: For compiling .mist contracts into deployable bundles
  • VS Code: Recommended IDE with Rust and TypeScript extensions

Quick Start (5 minutes)

1. Clone and Build

# Clone the repository
git clone https://github.com/rivellum/rivellum.git
cd rivellum

# Build all crates in release mode
cargo build --release

# Run tests to verify
cargo test --workspace

Expected build time: 2-5 minutes on modern hardware.

2. Start a Local Node

# Run with default configuration
.\target\release\rivellum-node.exe --config config\dev.toml

You should see:

[INFO] Starting Rivellum node...
[INFO] Network listening on /ip4/127.0.0.1/tcp/9000
[INFO] RPC server listening on 127.0.0.1:8545
[INFO] Node ready! ID: 12D3KooW...

3. Submit Your First Intent

Create my-intent.jsonl:

{"intent_id":"0x1234","from":"0xalice","nonce":0,"payload":{"Plain":[1,2,3]},"signature":"0xabc...","max_fee":1000}

Submit using CLI:

.\target\release\rivellum-node.exe intent submit my-intent.jsonl

Or using the TypeScript SDK:

import { RivellumClient } from '@rivellum/sdk';

const client = new RivellumClient('https://rpc.rivellum.network');
// Build encrypted envelope and submit via sealed-batch ingress
const envelope = await buildEncryptedEnvelope({
  from: '0xalice',
  payload: { type: 'transfer', to: '0xbob', amount: 100 },
});
await client.submitEnvelope(envelope);

Architecture Refresher

Before diving deeper, understand these core concepts:

  • Intents: User declarations of desired outcomes (not imperative transactions)
  • Batches: Groups of intents processed together for efficiency
  • Shards: Parallel execution contexts (Aurora Fabric)
  • Photon: BFT consensus algorithm with instant finality
  • PoUW: Proof-of-Useful-Work for ZK proof generation

See Architecture Overview for full details.

Development Workflow

Project Structure

rivellum/
ā”œā”€ā”€ crates/              # Rust workspace
│   ā”œā”€ā”€ rivellum-node/    # Main binary
│   ā”œā”€ā”€ rivellum-intents/ # Intent types & validation
│   ā”œā”€ā”€ rivellum-execution/ # Aurora Fabric execution
│   ā”œā”€ā”€ rivellum-ledger/  # State & storage
│   ā”œā”€ā”€ rivellum-network/ # P2P networking
│   ā”œā”€ā”€ rivellum-crypto/  # Cryptographic primitives
│   ā”œā”€ā”€ rivellum-zk/      # ZK proof system
│   ā”œā”€ā”€ rivellum-pouw/    # Proof-of-Useful-Work
│   └── ...
ā”œā”€ā”€ sdk/                 # TypeScript SDK
ā”œā”€ā”€ explorer/            # Block explorer UI
ā”œā”€ā”€ portal/              # Developer portal & academy
ā”œā”€ā”€ contracts/           # Mist smart contracts (`.mist`)
ā”œā”€ā”€ config/              # Node configuration files
└── docs/                # Documentation (you are here!)

Configuration Files

Rivellum uses TOML configuration files in config/:

  • dev.toml: Local development (single node, mock ZK)
  • testnet.toml: Multi-node testnet
  • mainnet.example.toml: Production template
  • zk-real.toml: Enable real ZK proofs (requires prover)

Key settings:

chain_id = "devnet"

[network]
listen_addr = "127.0.0.1:9000"
bootstrap_peers = []
max_peers = 50

[rpc]
listen_addr = "127.0.0.1:8545"
max_concurrent_requests = 1000
request_timeout_secs = 30

[execution]
workers_per_committee = 4
max_queue_size = 50000
gas_limit = 1000000
lane_count = 4

[execution.sequencer]
window_k = 4
max_buffered_per_sender = 16
max_nonce_gap = 100

[events]
backend = "in_memory"
data_dir = "./data/events"
max_in_memory_events = 100000
durability = "async"

[startup]
seed_prefab_registry = true

Building Specific Crates

# Build only the node binary
cargo build --release --package rivellum-node

# Build with optimizations for size
cargo build --release --package rivellum-node --profile=release-small

# Check code without building
cargo check --workspace

# Run clippy linter
cargo clippy --workspace -- -D warnings

Running Tests

# Run all tests
cargo test --workspace

# Run tests for specific crate
cargo test --package rivellum-intents

# Run integration tests only
cargo test --test integration_tests

# Run with output
cargo test --workspace -- --nocapture

# Run specific test
cargo test test_intent_validation

Code Formatting

# Format all code
cargo fmt --all

# Check formatting without changes
cargo fmt --all -- --check

Working with Intents

Intent Structure

pub struct Intent {
    pub intent_id: IntentId,        // Unique identifier
    pub from: Address,               // Sender address
    pub nonce: u64,                  // Replay protection
    pub payload: PayloadKind,        // Plain or Encrypted
    pub signature: Signature,        // EdDSA signature
    pub max_fee: u64,                // Maximum fee willing to pay
}

Creating Intents Programmatically

Rust:

use rivellum_intents::{Intent, IntentId, PayloadKind};
use rivellum_crypto::{KeyPair, sign_intent};

let keypair = KeyPair::generate();
let intent = Intent {
    intent_id: IntentId::random(),
    from: keypair.public_key().to_address(),
    nonce: 0,
    payload: PayloadKind::Plain(vec![1, 2, 3]),
    signature: Signature::default(),  // Placeholder
    max_fee: 1000,
};

let signed = sign_intent(&intent, &keypair)?;

TypeScript SDK:

import { RivellumClient, Wallet } from '@rivellum/sdk';

const wallet = Wallet.fromMnemonic('your seed phrase...');
const client = new RivellumClient('https://rpc.rivellum.network');

const intent = await client.createIntent({
  from: wallet.address,
  payload: {
    type: 'custom',
    data: [1, 2, 3],
  },
  maxFee: 1000,
});

const signed = await wallet.signIntent(intent);
const envelope = await buildEncryptedEnvelope(signed);
await client.submitEnvelope(envelope);

Intent Types

Rivellum supports various built-in intent types:

  1. Transfer: Send tokens between accounts
  2. Contract Call: Invoke Mist contract functions
  3. Contract Deploy: Deploy Mist bundles
  4. Batch: Execute multiple operations atomically
  5. Custom: Application-specific payloads

Example transfer intent:

{
  type: 'transfer',
  to: '0xrecipient',
  amount: 100,
  token: '0x1::Coin::RIVL',  // Native token
}

Smart Contracts with Mist

Write a Mist Contract

Create Counter.mist:

contract Counter
    function ping() -> Int
        return 1

Compile with mistc

# Build a deployable Mist bundle
mistc build --output-dir ./build ./Counter.mist

Deploy a Mist Bundle

curl -X POST https://rpc.rivellum.network/v1/mist/deploy `
  -H "Content-Type: application/octet-stream" `
  --data-binary "@./build/Counter.bundle.json"

Call a Mist Contract

curl -X POST https://rpc.rivellum.network/v1/mist/call/<contract_id> `
  -H "Content-Type: application/json" `
  -d '{"function":"ping","args":{}}'

Use GET /v1/mist/receipts/<intent_id> to track finalization.

Using the TypeScript SDK

Installation

npm install @rivellum/sdk

Basic Usage

import { RivellumClient, Wallet } from '@rivellum/sdk';

// Connect to node
const client = new RivellumClient('https://rpc.rivellum.network');

// Create wallet from private key
const wallet = Wallet.fromPrivateKey('0x123...');

// Check balance
const balance = await client.getBalance(wallet.address);
console.log('Balance:', balance);

// Submit transfer intent
const txHash = await client.transfer({
  from: wallet.address,
  to: '0xrecipient',
  amount: 100,
  signer: wallet,
});

// Wait for finality
const receipt = await client.waitForFinality(txHash);
console.log('Finalized in block:', receipt.blockNumber);

Advanced SDK Features

Batch Intents:

const batch = client.createBatch();
batch.addTransfer({ to: '0xalice', amount: 50 });
batch.addTransfer({ to: '0xbob', amount: 50 });
batch.addContractCall({
  module: 'MyModule::MyContract',
  function: 'do_something',
  args: [42],
});

const txHash = await batch.submit(wallet);

Query State:

// Get account info
const account = await client.getAccount('0xaddress');
console.log('Nonce:', account.nonce);
console.log('Balance:', account.balance);

// Get batch by ID
const batch = await client.getBatch('0xbatchhash');
console.log('Intents:', batch.intents.length);
console.log('Status:', batch.status);

// Listen for events
client.on('batchFinalized', (batch) => {
  console.log('New batch finalized:', batch.id);
});

Local Development Tools

Block Explorer

Monitor your local node in real-time:

cd explorer  
npm install
npm run dev
# Open https://explorer.rivellum.network

Shows:

  • Recent batches and intents
  • Account balances and nonces
  • Shard utilization
  • PoUW proof status

RPC API Testing

Use curl to test RPC endpoints directly:

# Get node info
curl https://rpc.rivellum.network/info

# Get account balance
curl -X POST https://rpc.rivellum.network/rpc `
  -H "Content-Type: application/json" `
  -d '{\"jsonrpc\":\"2.0\",\"method\":\"getBalance\",\"params\":[\"0xaddress\"],\"id\":1}'

# Submit encrypted envelope
curl -X POST https://rpc.rivellum.network/v1/submit_envelope `
  -H "Content-Type: application/json" `
  -d '{"version":1,"envelope_id":"0x...","sender":"0x...","nonce":0,"lane_hint":0,"epoch_id":0,"max_fee":1000000,"ciphertext":[...],"encryption_nonce":[...],"signature":[...],"signing_key":[...]}'

Running a Multi-Node Devnet

For consensus testing, run multiple nodes:

# Start 3-node devnet with Docker
cd devnet
docker-compose up -d

# Check logs
docker-compose logs -f leader
docker-compose logs -f follower1
docker-compose logs -f follower2

# Shutdown
docker-compose down

Or manually:

# Terminal 1: Leader
rivellum-node.exe --config devnet\leader.toml

# Terminal 2: Follower 1
rivellum-node.exe --config devnet\follower1.toml

# Terminal 3: Follower 2  
rivellum-node.exe --config devnet\follower2.toml

Debugging Tips

Enable Verbose Logging

# In your config.toml
[node]
log_level = "debug"  # or "trace" for max verbosity

# Per-crate logging
[logging]
"rivellum_intents" = "debug"
"rivellum_execution" = "trace"
"rivellum_network" = "info"

Common Issues

Issue: Error: nonce mismatch Solution: Each intent must have nonce = previous_nonce + 1. Query current nonce:

curl https://rpc.rivellum.network/account/0xaddress | jq .nonce

Issue: Error: insufficient balance Solution: Check balance and ensure max_fee doesn't exceed available funds:

curl https://rpc.rivellum.network/account/0xaddress | jq .balance

Issue: Error: signature verification failed Solution: Ensure you're signing the intent correctly. The signature covers:

hash(intent_id || from || nonce || payload_hash || max_fee)

Issue: Node won't start - "Address already in use" Solution: Change listen ports in config or kill existing process:

Get-Process rivellum-node | Stop-Process

Using Rust Debugger

# Build with debug symbols
cargo build --package rivellum-node

# Run with lldb (or gdb on Linux)
rust-lldb .\target\debug\rivellum-node.exe -- --config config\dev.toml

Or use VS Code debugger with .vscode/launch.json:

{
  "type": "lldb",
  "request": "launch",
  "name": "Debug rivellum-node",
  "cargo": {
    "args": ["build", "--package=rivellum-node"]
  },
  "args": ["--config", "config/dev.toml"]
}

Performance Profiling

Benchmarking

# Run built-in benchmarks
cargo bench --package rivellum-intents

# Profile with flamegraph
cargo install flamegraph
cargo flamegraph --package rivellum-node -- --config config\dev.toml

Load Testing

# Generate 10,000 test intents
.\scripts\generate-test-intents.ps1 -Count 10000 -Output test-intents.jsonl

# Submit with parallel workers
.\scripts\load-test.ps1 -Intents test-intents.jsonl -Workers 10

Next Steps

Now that you have a working development environment:

  1. Build a dApp: See SDK Guide for full API reference
  2. Write Smart Contracts: Follow the Mist workflow in Smart Contracts with Mist
  3. Run a Prover: Learn PoUW Setup to earn rewards
  4. Deploy to Testnet: Follow Node Setup guide