RougeChain Documentation

Welcome to RougeChain — a post-quantum secure Layer 1 blockchain built with real NIST-approved cryptography.

What is RougeChain?

RougeChain is the first blockchain designed from the ground up to be resistant to quantum computer attacks. It uses:

  • ML-DSA-65 (CRYSTALS-Dilithium) for digital signatures
  • ML-KEM-768 (CRYSTALS-Kyber) for key encapsulation
  • SHA-256 for hashing

All cryptographic primitives are NIST FIPS 204/203 compliant.

Key Features

FeatureDescription
Post-Quantum SecurityProtected against both classical and quantum attacks
Client-Side SigningPrivate keys never leave your browser
AMM/DEXUniswap V2-style liquidity pools and token swaps
Token BurningOfficial burn address with on-chain tracking
Proof of StakeEnergy-efficient consensus with validator staking
P2P NetworkDecentralized peer-to-peer block and transaction propagation
qETH BridgeBridge ETH from Base Sepolia to qETH on RougeChain
Custom TokensCreate your own tokens on the network
RC-721 NFTsNFT collections with royalties, batch minting, and freezing
Encrypted MessengerE2E encrypted messaging with PQC, media support, self-destruct
PQC MailEncrypted email with @rouge.quant addresses and threading
Browser ExtensionsChrome/Firefox wallet extensions with vault lock
PWA SupportInstallable progressive web app for mobile and desktop
SDK@rougechain/sdk npm package for building dApps
Open SourceFully open source Rust backend and React frontend

Network Info

NetworkAPI Endpoint
Testnethttps://testnet.rougechain.io/api
Devnet (local)http://127.0.0.1:5100/api

Tokens

XRGE

The native token of RougeChain is XRGE (pronounced "rouge").

qETH

qETH is a bridged representation of ETH on RougeChain. It uses 6 decimal places and can be bridged in from Base Sepolia or withdrawn back.

PropertyValue
Decimals6
Bridge SourceBase Sepolia
Bridge ContractConfigured per-node via --bridge-custody-address

Fees

ActionFee
Transfer0.1 XRGE
Token Creation100 XRGE
Pool Creation10 XRGE
Swap0.3% (to LPs)
Minimum Stake1,000 XRGE

Burn Address

Tokens can be permanently burned by sending to the official burn address:

XRGE_BURN_0x000000000000000000000000000000000000000000000000000000000000DEAD

Burned tokens are tracked on-chain and can be queried via the /api/burned endpoint.

Security

Client-Side Signing

RougeChain uses a secure v2 API where all transactions are signed client-side:

  1. Your wallet creates a transaction payload
  2. The payload is signed locally using ML-DSA-65
  3. Only the signature and public key are sent to the server
  4. Your private key never leaves your browser

This ensures maximum security even when interacting with untrusted nodes.

Getting Started

This guide will help you get up and running with RougeChain in minutes.

Prerequisites

  • A modern web browser (Chrome, Firefox, Edge, Safari)
  • For running a node: Rust toolchain (1.70+)

Quickest Path

  1. Visit rougechain.io
  2. Click "Wallet" in the sidebar
  3. Your wallet is automatically created and stored locally
  4. Use the faucet to get free testnet XRGE

That's it! You now have a quantum-secure wallet.

What's Next?

Quick Start

Get started with RougeChain in 5 minutes.

Step 1: Access the Web App

Visit rougechain.io or run locally:

git clone https://github.com/cyberdreadx/quantum-vault
cd quantum-vault
npm install
npm run dev

Open http://localhost:5173 in your browser.

Step 2: Create Your Wallet

Your wallet is created automatically when you first visit. It includes:

  • Public Key (ML-DSA-65) - Your address, share freely
  • Private Key (ML-DSA-65) - Never share this!
  • Encryption Key (ML-KEM-768) - For secure messaging

Keys are stored locally in your browser.

Step 3: Get Test Tokens

  1. Click Wallet in the sidebar
  2. Click Request from Faucet
  3. Receive 1,000 XRGE instantly

Step 4: Send Your First Transaction

  1. Click Send
  2. Enter recipient address
  3. Enter amount
  4. Click Send XRGE

Transaction is signed with your ML-DSA-65 key and broadcast to the network.

Step 5: View on Blockchain

  1. Click Blockchain in sidebar
  2. See your transaction in the latest block
  3. Verify the PQC signature

What's Next?

Troubleshooting

"Failed to fetch" Error

  • Check if you're connected to the right network (Testnet vs Devnet)
  • Ensure the node is running if using local devnet

"Insufficient balance"

  • Transaction requires amount + 0.1 XRGE fee
  • Use faucet to get more tokens

Wallet not loading

  • Clear browser cache
  • Check browser console for errors

Create a Wallet

Your RougeChain wallet is automatically created when you first visit the app. Here's what you need to know about it.

Wallet Components

ComponentAlgorithmPurpose
Signing KeyML-DSA-65Sign transactions, prove ownership
Encryption KeyML-KEM-768Encrypt/decrypt messages

Your Public Key = Your Address

Your public key (signing key) is your address on RougeChain. It's safe to share.

Example address:

9c88d3ec652bb98aea33e601c351e3c597661b1a...

Addresses are ~2,600 characters (base64 encoded ML-DSA-65 public key).

Backup Your Wallet

CRITICAL: Your private key is only stored in your browser. If you clear browser data, you lose access to your funds.

Export Backup

  1. Go to Wallet page
  2. Click Backup or the key icon
  3. Save the backup file securely

Restore from Backup

  1. Go to Wallet page
  2. Click Restore
  3. Upload your backup file

Security Best Practices

  1. Never share your private key
  2. Backup your wallet immediately
  3. Use a password manager to store your backup
  4. Don't screenshot your keys
  5. Verify addresses before sending

Technical Details

Key Generation

// Signing keypair (ML-DSA-65)
const signingSeed = crypto.getRandomValues(new Uint8Array(32));
const signingKeypair = ml_dsa65.keygen(signingSeed);

// Encryption keypair (ML-KEM-768)
const encryptionSeed = crypto.getRandomValues(new Uint8Array(32));
const encryptionKeypair = ml_kem768.keygen(encryptionSeed);

Storage

Keys are stored in browser localStorage:

localStorage.getItem('pqc-wallet-keys')

For production, consider:

  • IndexedDB with encryption
  • Hardware wallet integration
  • Server-side encrypted backup

Get Test Tokens

The faucet distributes free XRGE tokens for testing on testnet.

Using the Web UI

  1. Go to the Wallet page
  2. Click Request from Faucet
  3. Receive 1,000 XRGE instantly

Using the API

curl -X POST https://testnet.rougechain.io/api/faucet \
  -H "Content-Type: application/json" \
  -d '{"publicKey": "your-public-key-here"}'

Response:

{
  "success": true,
  "amount": 1000,
  "txId": "abc123..."
}

Rate Limits

ConditionLimit
Per address1 request / hour
Per IP10 requests / hour
WhitelistedUnlimited

Whitelisting

For development or testing, addresses can be whitelisted:

# Start node with whitelist
./quantum-vault-daemon --mine \
  --faucet-whitelist "pubkey1,pubkey2,pubkey3"

# Or via environment variable
export QV_FAUCET_WHITELIST="pubkey1,pubkey2"
./quantum-vault-daemon --mine

Troubleshooting

"Rate limited"

Wait an hour or use a different address.

"Faucet disabled"

The node may not have faucet enabled. Check node configuration.

Transaction not appearing

  1. Check the block explorer for your tx
  2. Verify you're on the correct network
  3. Wait for the next block (1-2 seconds)

Running a Node

Run your own RougeChain node to participate in the network, validate transactions, and earn rewards.

Node Types

TypeDescriptionRequires
Full NodeSyncs and validates all blocks--peers
Mining NodeProduces new blocks--mine
Public NodeAccepts external connections--host 0.0.0.0

Quick Start

# Build the daemon
cd core
cargo build --release -p quantum-vault-daemon

# Run a syncing node
./target/release/quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

# Run a mining node
./target/release/quantum-vault-daemon \
  --mine \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

Verify It's Working

curl http://127.0.0.1:5100/api/health

Expected response:

{
  "status": "ok",
  "chain_id": "rougechain-devnet-1",
  "height": 123
}

Next Steps

Installation

Build and run a RougeChain node from source.

Prerequisites

Linux / macOS

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env

# Install build dependencies (Ubuntu/Debian)
sudo apt update && sudo apt install -y build-essential pkg-config libssl-dev

# Install build dependencies (macOS)
xcode-select --install

Windows

  1. Install Rust
  2. Install Visual Studio Build Tools
  3. Ensure cargo is in your PATH

Build from Source

# Clone the repository
git clone https://github.com/cyberdreadx/quantum-vault
cd quantum-vault/core

# Build release binary
cargo build --release -p quantum-vault-daemon

# Binary location
./target/release/quantum-vault-daemon --help

Verify Installation

./target/release/quantum-vault-daemon --version

Expected output:

quantum-vault-daemon 0.1.0

First Run

Option A: Connect to Testnet

./target/release/quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

Option B: Start Local Devnet

./target/release/quantum-vault-daemon --mine --api-port 5100

Verify Node is Running

curl http://127.0.0.1:5100/api/health

Expected response:

{"status":"ok","chain_id":"rougechain-devnet-1","height":0}

Directory Structure

After first run, data is stored at:

OSDefault Location
Linux/macOS~/.quantum-vault/core-node/
WindowsC:\Users\<you>\.quantum-vault\core-node\

Updating

cd quantum-vault
git pull
cd core
cargo build --release -p quantum-vault-daemon

# Restart the node

Troubleshooting

"cargo not found"

source ~/.cargo/env
# or restart your terminal

"OpenSSL not found"

# Ubuntu/Debian
sudo apt install libssl-dev pkg-config

# Fedora/RHEL
sudo dnf install openssl-devel

# macOS
brew install openssl

"Address already in use"

Another process is using port 5100:

# Find and kill it
lsof -i :5100
kill -9 <PID>

# Or use a different port
./quantum-vault-daemon --api-port 5101

Build fails on Windows

Ensure you have Visual Studio Build Tools with C++ workload installed.

Configuration

All node configuration is done via command-line flags or environment variables.

CLI Options

FlagEnv VariableDefaultDescription
--host-127.0.0.1Bind address for API/gRPC
--port-4100gRPC port
--api-port-5100HTTP API port
--chain-id-rougechain-devnet-1Chain identifier
--block-time-ms-1000Block production interval (ms)
--mine-falseEnable block production
--data-dir-~/.quantum-vault/core-nodeData storage directory
--peersQV_PEERS-Comma-separated peer URLs
--public-urlQV_PUBLIC_URL-This node's public URL for discovery
--api-keysQV_API_KEYS-Comma-separated API keys
--rate-limit-per-minute-120Rate limit for API requests

Examples

Local Development Node

./quantum-vault-daemon --mine --api-port 5100

Syncing Node (No Mining)

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

Public Mining Node

./quantum-vault-daemon \
  --mine \
  --host 0.0.0.0 \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io" \
  --public-url "https://mynode.example.com"

Multiple Peers

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://node1.example.com,https://node2.example.com,https://node3.example.com"

Custom Data Directory

./quantum-vault-daemon \
  --mine \
  --api-port 5100 \
  --data-dir "/var/lib/rougechain"

Environment Variables

You can also use environment variables:

export QV_PEERS="https://testnet.rougechain.io"
export QV_PUBLIC_URL="https://mynode.example.com"
export QV_API_KEYS="key1,key2,key3"

./quantum-vault-daemon --mine --api-port 5100

Data Directory Structure

~/.quantum-vault/core-node/
├── chain.jsonl          # Block data (append-only)
├── tip.json             # Current chain tip
├── validators-db/       # Validator state (RocksDB)
└── messenger-db/        # Messenger data (RocksDB)

Running with Systemd (Linux)

Create /etc/systemd/system/rougechain.service:

[Unit]
Description=RougeChain Node
After=network.target

[Service]
Type=simple
User=rougechain
ExecStart=/opt/rougechain/quantum-vault-daemon --mine --host 0.0.0.0 --api-port 5100 --peers "https://testnet.rougechain.io"
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable rougechain
sudo systemctl start rougechain
sudo journalctl -u rougechain -f  # View logs

Mining (Block Production)

RougeChain uses Proof of Stake, so "mining" refers to block production by validators rather than proof-of-work mining.

Enable Mining

Start your node with the --mine flag:

./quantum-vault-daemon --mine --api-port 5100

This tells the node to produce blocks at the configured interval (default: 1000ms).

Requirements

RequirementValue
Staked XRGEMinimum 1,000 XRGE
Node uptimeMust be online to produce blocks
Network syncNode must be synced to chain tip

How Block Production Works

  1. Validator selection — Each block slot, the network selects a proposer based on stake weight and quantum entropy
  2. Block assembly — The selected validator collects pending transactions from the mempool
  3. Signing — The block is signed with the validator's ML-DSA-65 key
  4. Propagation — The signed block is broadcast to all peers via POST /api/blocks/import
  5. Verification — Receiving nodes verify the signature and block validity before accepting

Block Timing

ParameterDefaultFlag
Block time1000ms--block-time-ms
# Slower blocks (5 seconds)
./quantum-vault-daemon --mine --block-time-ms 5000

# Faster blocks (500ms, for local dev)
./quantum-vault-daemon --mine --block-time-ms 500

Mining with Peers

To mine as part of the network (not solo):

./quantum-vault-daemon \
  --mine \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io" \
  --public-url "https://mynode.example.com"

The --public-url flag is important — it lets other nodes discover and sync from you.

Monitoring

Check your validator status:

curl https://testnet.rougechain.io/api/validators

Check blocks produced:

curl https://testnet.rougechain.io/api/blocks?limit=10

Rewards

Validators earn transaction fees from blocks they produce. Fees are credited immediately when a block is finalized. See Staking Rewards for details.

Troubleshooting

Node not producing blocks

  • Ensure --mine flag is set
  • Verify you have enough XRGE staked (min 1,000)
  • Check that your node is synced: curl http://127.0.0.1:5100/api/health

Blocks not propagating

  • Ensure --public-url is set and accessible from the internet
  • Check firewall rules for your API port
  • Verify peer connections: curl http://127.0.0.1:5100/api/peers

Producing blocks but no rewards

  • Confirm your staking transaction was included in a block
  • Check validator status via the API

P2P Networking

RougeChain uses a peer-to-peer network for block propagation, transaction broadcasting, and peer discovery.

How It Works

┌─────────────┐     blocks/txs      ┌─────────────┐
│   Node A    │ ◄─────────────────► │   Node B    │
│  (mining)   │                     │  (syncing)  │
└─────────────┘                     └─────────────┘
       ▲                                   ▲
       │           peer discovery          │
       └───────────────┬───────────────────┘
                       │
                       ▼
               ┌─────────────┐
               │   Node C    │
               │ (new peer)  │
               └─────────────┘

Features

FeatureDescription
Block SyncNodes download and verify blocks from peers
Transaction BroadcastSubmitted txs propagate to all peers
Peer DiscoveryNodes share their peer lists with each other
Genesis ResetNew nodes automatically adopt the network's chain

Connecting to the Network

As a Syncing Node

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

As a Mining Node

./quantum-vault-daemon \
  --mine \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

Peer Discovery

Nodes automatically discover new peers every 30 seconds by:

  1. Querying known peers via GET /api/peers
  2. Adding any new peers to their list
  3. Optionally registering themselves via POST /api/peers/register

Enable Self-Registration

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io" \
  --public-url "https://mynode.example.com"

This tells other nodes how to reach you.

API Endpoints

EndpointMethodDescription
/api/peersGETList known peers
/api/peers/registerPOSTRegister as a peer
/api/blocks/importPOSTImport a block (peer-to-peer)
/api/tx/broadcastPOSTReceive a broadcasted transaction

Next Steps

Connecting to Peers

Connect your RougeChain node to the network to sync blocks and broadcast transactions.

Connect to Testnet

The simplest way to join the network:

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io"

Your node will:

  1. Download all blocks from the peer
  2. Verify each block's PQC signatures
  3. Build the local chain state
  4. Start receiving new blocks in real-time

Connect to Multiple Peers

For better reliability, connect to multiple peers:

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io,https://node2.example.com,https://node3.example.com"

Or via environment variable:

export QV_PEERS="https://testnet.rougechain.io,https://node2.example.com"
./quantum-vault-daemon --api-port 5100

Verify Connection

Check that your node has peers:

curl http://127.0.0.1:5100/api/peers

Expected response:

{
  "peers": [
    "https://testnet.rougechain.io/api"
  ],
  "count": 1
}

Sync Status

Check if your node is synced:

curl http://127.0.0.1:5100/api/health
{
  "status": "ok",
  "chain_id": "rougechain-devnet-1",
  "height": 12345
}

Compare the height with the testnet to confirm you're in sync:

curl https://testnet.rougechain.io/api/health

Connection Flow

Your Node                          Peer Node
    │                                  │
    │── GET /api/health ──────────────►│
    │◄─── { height: 12345 } ──────────│
    │                                  │
    │── GET /api/blocks?from=0 ───────►│
    │◄─── [ block0, block1, ... ] ────│
    │                                  │
    │   (verify signatures, apply)     │
    │                                  │
    │── GET /api/peers ───────────────►│
    │◄─── { peers: [...] } ───────────│
    │                                  │
    │   (discover new peers)           │

Firewall Configuration

If running behind a firewall, ensure the API port is accessible:

PortProtocolPurpose
5100 (default)TCP/HTTPREST API and P2P
# Linux (ufw)
sudo ufw allow 5100/tcp

# Linux (firewalld)
sudo firewall-cmd --add-port=5100/tcp --permanent
sudo firewall-cmd --reload

Troubleshooting

"Connection refused"

  • Check that the peer URL is correct and reachable
  • Verify the peer node is running
  • Check for firewall restrictions

Node stuck syncing

  • The initial sync may take time on long chains
  • Monitor progress by watching the height increase via /api/health
  • Try connecting to a different peer

"Chain ID mismatch"

  • Ensure your --chain-id matches the network you're connecting to
  • Testnet uses rougechain-devnet-1

Peer Discovery

RougeChain nodes automatically discover other nodes on the network through a gossip-based peer exchange protocol.

How Discovery Works

1. Node A starts with seed peer(s) via --peers
2. Node A queries GET /api/peers on each known peer
3. Each peer returns its own list of known peers
4. Node A adds any new peers to its local list
5. If --public-url is set, Node A registers itself on peers
6. Repeat every 30 seconds

Over time, all nodes in the network discover each other, forming a mesh.

Discovery Interval

Peer discovery runs automatically every 30 seconds. No configuration is needed.

Seed Peers

The first peer(s) you connect to act as seeds for discovery. From them, your node learns about the rest of the network.

# Single seed
./quantum-vault-daemon --peers "https://testnet.rougechain.io"

# Multiple seeds for redundancy
./quantum-vault-daemon --peers "https://testnet.rougechain.io,https://backup.example.com"

Self-Registration

To make your node discoverable by others, set --public-url:

./quantum-vault-daemon \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io" \
  --public-url "https://mynode.example.com"

Your node will call POST /api/peers/register on all known peers, announcing its presence. Other nodes will then include your URL in their peer lists.

Discovery API

Get Known Peers

curl http://127.0.0.1:5100/api/peers
{
  "peers": [
    "https://testnet.rougechain.io/api",
    "https://node2.example.com/api",
    "https://node3.example.com/api"
  ],
  "count": 3
}

Register as a Peer

curl -X POST https://testnet.rougechain.io/api/peers/register \
  -H "Content-Type: application/json" \
  -d '{"peerUrl": "https://mynode.example.com"}'

Discovery Diagram

         Seed Node
        ┌─────────┐
        │  Node A  │ ◄── your --peers target
        └────┬────┘
             │
     GET /api/peers
             │
    ┌────────┼────────┐
    ▼        ▼        ▼
┌───────┐┌───────┐┌───────┐
│Node B ││Node C ││Node D │  ◄── discovered automatically
└───────┘└───────┘└───────┘
    │         │        │
    └─────────┼────────┘
              │
    More peers discovered
       from B, C, D...

Privacy Considerations

  • Your node's IP/URL is shared with all peers when using --public-url
  • Without --public-url, your node connects outward but is not discoverable by others
  • Consider using a reverse proxy or domain name instead of exposing raw IP addresses

Running a Public Node

Run a RougeChain node that is publicly accessible and participates fully in the network.

Requirements

RequirementDetails
ServerVPS or dedicated server with a public IP
Domain (recommended)Point a domain to your server
SSL certificateRequired for HTTPS (use Let's Encrypt)
Open portAPI port accessible from the internet

Setup

1. Build and Install

git clone https://github.com/cyberdreadx/quantum-vault
cd quantum-vault/core
cargo build --release -p quantum-vault-daemon
sudo cp target/release/quantum-vault-daemon /usr/local/bin/

2. Configure Reverse Proxy (nginx)

server {
    listen 443 ssl;
    server_name mynode.rougechain.example.com;

    ssl_certificate /etc/letsencrypt/live/mynode.rougechain.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mynode.rougechain.example.com/privkey.pem;

    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:5100;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Set client_max_body_size to at least 50M to support messenger media uploads.

3. Start the Node

./quantum-vault-daemon \
  --mine \
  --host 127.0.0.1 \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io" \
  --public-url "https://mynode.rougechain.example.com"

4. Run as a Service

Create /etc/systemd/system/rougechain.service:

[Unit]
Description=RougeChain Node
After=network.target

[Service]
Type=simple
User=rougechain
ExecStart=/usr/local/bin/quantum-vault-daemon --mine --host 127.0.0.1 --api-port 5100 --peers "https://testnet.rougechain.io" --public-url "https://mynode.rougechain.example.com"
Restart=always
RestartSec=5
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
sudo useradd -r -s /bin/false rougechain
sudo systemctl enable rougechain
sudo systemctl start rougechain

Verify Your Node

Health Check

curl https://mynode.rougechain.example.com/api/health

Check Peers Can See You

curl https://testnet.rougechain.io/api/peers
# Your node's URL should appear in the list

Security Hardening

API Keys

Restrict write access with API keys:

./quantum-vault-daemon \
  --mine \
  --api-port 5100 \
  --api-keys "secret-key-1,secret-key-2"

Rate Limiting

The node has built-in rate limiting (default: 120 requests/minute). Adjust as needed:

./quantum-vault-daemon --rate-limit-per-minute 60

Firewall

Only expose the necessary port:

sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 443/tcp
sudo ufw enable

Monitoring

Check Logs

sudo journalctl -u rougechain -f

Health Endpoint

Set up a monitoring tool (e.g., UptimeRobot) to poll:

https://mynode.rougechain.example.com/api/health

Metrics to Watch

MetricHow to Check
Block heightGET /api/health — compare with testnet
Peer countGET /api/peers — should be > 0
Validator statusGET /api/validators — check your stake

Staking & Validators

RougeChain uses Proof of Stake (PoS) for consensus. Validators stake XRGE tokens to participate in block production and earn rewards.

How It Works

  1. Stake tokens - Lock XRGE to become a validator
  2. Propose blocks - Selected validators propose new blocks
  3. Earn rewards - Collect transaction fees from blocks you produce
  4. Unstake - Wait for unbonding period to withdraw

Requirements

RequirementValue
Minimum stake1,000 XRGE
Unbonding period~7 days
SlashingNot implemented (testnet)

Become a Validator

Via Web UI

  1. Go to the Validators page
  2. Click Stake
  3. Enter amount (min 1,000 XRGE)
  4. Confirm transaction

Via API

curl -X POST https://testnet.rougechain.io/api/stake/submit \
  -H "Content-Type: application/json" \
  -d '{
    "fromPrivateKey": "your-private-key",
    "fromPublicKey": "your-public-key",
    "amount": 1000
  }'

Check Your Stake

curl "https://testnet.rougechain.io/api/validators?publicKey=your-public-key"

Response:

{
  "validators": [
    {
      "publicKey": "your-public-key",
      "stake": 1000.0,
      "status": "active",
      "blocksProposed": 42
    }
  ]
}

Unstake

Via API

curl -X POST https://testnet.rougechain.io/api/unstake/submit \
  -H "Content-Type: application/json" \
  -d '{
    "fromPrivateKey": "your-private-key",
    "fromPublicKey": "your-public-key",
    "amount": 500
  }'

Validator Selection

Block proposers are selected using:

  1. Stake weight - Higher stake = higher probability
  2. Quantum entropy - Unpredictable randomness
  3. Round-robin fallback - Ensures all validators participate

Rewards

Validators earn:

  • Transaction fees from blocks they produce
  • Base block reward (if configured)

Fees are credited immediately when a block is finalized.

PQC Security

All validator operations use ML-DSA-65 signatures:

  • Block proposals are signed
  • Stake/unstake transactions are signed
  • Signatures are verified by all nodes

This ensures quantum-resistant security for the entire consensus process.

Becoming a Validator

Validators produce blocks and earn transaction fees on RougeChain. This guide walks you through the full process.

Prerequisites

RequirementDetails
XRGE balanceAt least 1,000 XRGE (+ fees)
WalletA RougeChain wallet with signing keys
Node (optional)Running a node earns you more blocks

Step 1: Get XRGE

If you're on testnet, use the faucet:

  1. Visit rougechain.io
  2. Go to Wallet and click Request from Faucet
  3. Repeat until you have at least 1,000 XRGE

Step 2: Stake Tokens

Via Web UI

  1. Navigate to the Validators page
  2. Click Stake
  3. Enter your stake amount (minimum 1,000 XRGE)
  4. Confirm the transaction
  5. Your wallet signs the stake transaction with ML-DSA-65

Via v2 API (Client-Side Signing)

curl -X POST https://testnet.rougechain.io/api/v2/stake \
  -H "Content-Type: application/json" \
  -d '{
    "publicKey": "your-public-key-hex",
    "amount": 1000,
    "nonce": 1706745600000,
    "signature": "your-ml-dsa65-signature-hex"
  }'

Step 3: Verify Your Validator Status

curl "https://testnet.rougechain.io/api/validators"

Look for your public key in the response:

{
  "validators": [
    {
      "publicKey": "your-public-key",
      "stake": 1000.0,
      "status": "active",
      "blocksProposed": 0
    }
  ]
}

While staking alone makes you a validator, running a node ensures you're online to produce blocks when selected:

./quantum-vault-daemon \
  --mine \
  --api-port 5100 \
  --peers "https://testnet.rougechain.io" \
  --public-url "https://mynode.example.com"

Increasing Your Stake

You can add more XRGE to increase your block proposal probability:

# Stake additional 500 XRGE
curl -X POST https://testnet.rougechain.io/api/v2/stake \
  -H "Content-Type: application/json" \
  -d '{
    "publicKey": "your-public-key-hex",
    "amount": 500,
    "nonce": 1706745600001,
    "signature": "your-signature-hex"
  }'

Your total stake accumulates.

Validator Selection Algorithm

Proposer selection uses three factors:

  1. Stake weight — Higher stake gives proportionally higher probability
  2. Quantum entropy — Ensures unpredictable selection
  3. Round-robin fallback — Guarantees all validators eventually participate

This means even validators with the minimum stake will produce blocks, just less frequently.

Leaving the Validator Set

See Unstaking — after unstaking below the minimum, you're removed from the active validator set.

Staking Rewards

Validators earn rewards for producing blocks on RougeChain.

Reward Sources

SourceDescription
Transaction feesAll fees from transactions in your block
Base block rewardFixed reward per block (if configured)

How Rewards Work

  1. A validator is selected to propose a block
  2. The validator assembles pending transactions
  3. All transaction fees in that block go to the proposer
  4. Rewards are credited immediately upon block finalization

Fee Structure

Transaction TypeFee
Transfer0.1 XRGE
Token creation100 XRGE
Pool creation10 XRGE
Swap0.3% (to LPs, not validators)
Stake/Unstake0.1 XRGE

Validators earn the flat fees (transfer, token creation, pool creation, stake/unstake). Swap fees go to liquidity providers.

Estimated Returns

Rewards depend on:

  • Your stake relative to total staked — determines how often you're selected
  • Network activity — more transactions = more fees per block
  • Number of validators — fewer validators means more blocks per validator

Example

ScenarioValue
Your stake10,000 XRGE
Total staked100,000 XRGE
Your share10%
Blocks per day~86,400 (1s block time)
Your blocks per day~8,640
Avg fee per block0.5 XRGE
Daily earnings~4,320 XRGE

These are approximate — actual returns vary with network conditions.

Compounding

Rewards are added to your balance, not your stake. To compound:

  1. Periodically stake your accumulated rewards
  2. This increases your proposer probability
  3. Leading to more blocks and more rewards

Checking Rewards

Via Web UI

Go to the Validators page to see your validator stats including blocks proposed.

Via API

# Check your balance (includes accumulated rewards)
curl "https://testnet.rougechain.io/api/balance/your-public-key"

# Check blocks proposed
curl "https://testnet.rougechain.io/api/validators"

Tax Considerations

Staking rewards may be taxable income in your jurisdiction. Keep records of:

  • Amount staked
  • Rewards received (block by block)
  • Token price at time of receipt
  • Unstaking transactions

RougeChain does not provide tax advice. Consult a tax professional.

Bridge

RougeChain supports bridging assets between Base Sepolia (EVM) and the RougeChain L1 network. The bridge uses a lock-and-mint / burn-and-release model with a dedicated smart contract.

Supported Assets

EVM AssetRougeChain AssetDecimalsDirection
ETHqETH6 (L1 units)Both ways
USDCqUSDC6Both ways
XRGEXRGE18 (EVM) / whole units (L1)Both ways

How It Works

Deposit (EVM → RougeChain)

  1. User deposits ETH, USDC, or XRGE into the RougeBridge smart contract on Base Sepolia
  2. User calls the claim endpoint on RougeChain with the EVM transaction hash
  3. The node verifies the deposit on-chain and mints the wrapped token (qETH, qUSDC, or XRGE) on L1

Withdrawal (RougeChain → EVM)

  1. User submits a signed bridge_withdraw transaction on RougeChain, burning the wrapped token
  2. The withdrawal is recorded in the pending withdrawals store
  3. The bridge relayer polls for pending withdrawals and releases the corresponding asset from the contract on EVM

Security

  • Client-side signing — Private keys never leave the browser. Withdraw transactions are signed locally using ML-DSA-65
  • RougeBridge contract — Pausable, with guardian role for emergencies, timelock on large withdrawals
  • Relayer authentication — The relayer uses a BRIDGE_RELAYER_SECRET for API authentication
  • Replay protection — Claimed transaction hashes are persisted to prevent double-claims
  • EVM signature verification — ETH claims require an EVM personal_sign to prove deposit ownership

Architecture

Base Sepolia (EVM)              RougeChain L1
┌──────────────────┐           ┌──────────────────┐
│  RougeBridge.sol │           │  Node Daemon     │
│  - depositETH() │──relayer──│  - /bridge/claim  │
│  - depositERC20()│           │  - /bridge/withdraw│
│  - releaseETH() │◀─relayer──│  - withdraw store │
│  - releaseERC20()│           │                  │
│  BridgeVault.sol │           │                  │
│  - deposit()     │──relayer──│  - /bridge/xrge/* │
│  - release()     │◀─relayer──│                  │
└──────────────────┘           └──────────────────┘

ETH Bridge (qETH)

Bridge ETH from Base Sepolia to RougeChain as qETH, and back.

Deposit (ETH → qETH)

Step 1: Send ETH to the Bridge

Connect your MetaMask (or other EVM wallet) to Base Sepolia and send ETH to the custody/bridge contract address shown on the Bridge page.

Step 2: Claim qETH

  1. Go to the Bridge page and select the Bridge In tab
  2. Paste the EVM transaction hash
  3. Sign the claim message with your EVM wallet (proves you made the deposit)
  4. Click Claim

The node verifies:

  • The transaction exists on Base Sepolia
  • It was sent to the correct custody address
  • The EVM signature matches the sender
  • The transaction has sufficient confirmations
  • It hasn't been claimed before

On success, qETH is minted to your RougeChain wallet.

Conversion Rate

1 ETH = 1,000,000 qETH units (6 decimal precision)

For example, depositing 0.01 ETH gives you 10,000 qETH units.

Withdraw (qETH → ETH)

  1. Go to the Bridge page and select the Bridge Out tab
  2. Select ETH as the token
  3. Enter the amount of qETH to bridge out
  4. Enter the Base Sepolia address to receive ETH
  5. Click Bridge Out

The transaction is signed client-side (your private key never leaves the browser), then:

  • qETH is burned on RougeChain
  • A pending withdrawal is created
  • The bridge relayer picks it up and sends ETH to your EVM address

A 0.1 XRGE fee is charged for the withdrawal transaction.

Fees

OperationFee
Deposit (ETH → qETH)Gas on Base Sepolia only
Withdraw (qETH → ETH)0.1 XRGE

USDC Bridge (qUSDC)

Bridge USDC from Base Sepolia to RougeChain as qUSDC, and back.

Overview

qUSDC is a wrapped representation of USDC on RougeChain. It maintains a 1:1 peg with USDC locked in the RougeBridge contract on Base Sepolia.

USDC Contract on Base Sepolia: 0x036CbD53842c5426634e7929541eC2318f3dCF7e

Deposit (USDC → qUSDC)

  1. Approve the RougeBridge contract to spend your USDC
  2. Call depositERC20(usdc_address, amount, rougechainPubkey) on the contract
  3. Go to the Bridge page, select USDC as the token, switch to Bridge In
  4. Paste the EVM transaction hash and claim

The node parses the ERC-20 Transfer event from the transaction receipt to determine the amount. USDC uses 6 decimals, and qUSDC uses the same 6-decimal precision.

Withdraw (qUSDC → USDC)

  1. Go to Bridge page, select USDC, switch to Bridge Out
  2. Enter amount and destination EVM address
  3. Click Bridge Out qUSDC

The relayer calls releaseERC20() on the RougeBridge contract to send USDC back to your EVM address.

Fees

OperationFee
DepositGas on Base Sepolia
Withdraw0.1 XRGE

XRGE Bridge

Bridge XRGE tokens between Base (EVM) and RougeChain L1 using the BridgeVault contract.

Overview

Unlike qETH/qUSDC (which are wrapped assets), XRGE is the native token of RougeChain. The XRGE bridge allows moving XRGE between its ERC-20 representation on Base and the L1 network.

XRGE Token on Base: 0x147120faEC9277ec02d957584CFCD92B56A24317

Deposit (Base XRGE → L1 XRGE)

  1. Approve the BridgeVault contract to spend your XRGE
  2. Call deposit(amount, rougechainPubkey) on the BridgeVault
  3. The vault locks your XRGE and emits a BridgeDeposit event
  4. Call the /api/bridge/xrge/claim endpoint with the transaction hash
  5. The node verifies the receipt and credits XRGE on L1

Withdraw (L1 XRGE → Base XRGE)

  1. Go to the Bridge page and use the XRGE Bridge Out tab
  2. Enter the amount and your Base EVM address
  3. Submit the signed withdrawal
  4. The relayer calls release() on the BridgeVault to unlock your XRGE on Base

BridgeVault Contract

The BridgeVault is a lock-and-release contract:

  • deposit(amount, rougechainPubkey) — Lock XRGE, emit event for relayer
  • release(to, amount, l1TxId) — Owner (relayer) releases XRGE back to user
  • vaultBalance() — View how much XRGE the vault holds
  • emergencyWithdraw(token) — Admin-only emergency recovery

Liquidity in the vault = total XRGE locked by depositors minus released amounts.

RougeBridge Contract

The RougeBridge.sol contract is a multi-asset bridge contract deployed on Base Sepolia that handles ETH and ERC-20 deposits/releases with enhanced security features.

Features

  • Multi-token support — ETH and any ERC-20 token (USDC, etc.)
  • Pausable — Guardian can pause all operations in emergencies
  • Timelock — Large withdrawals require a delay period before execution
  • Guardian role — Separate from owner; can pause but cannot withdraw
  • Replay protection — Processed L1 transaction IDs are tracked to prevent double-releases
  • Owner = multisig — Deploy with a Gnosis Safe as owner for production

Key Functions

Deposits

function depositETH(string calldata rougechainPubkey) external payable;
function depositERC20(address token, uint256 amount, string calldata rougechainPubkey) external;

Users call these to lock assets in the contract. Events are emitted for the relayer to pick up.

Releases (Owner Only)

function releaseETH(address to, uint256 amount, bytes32 l1TxId) external;
function releaseERC20(address token, address to, uint256 amount, bytes32 l1TxId) external;

The relayer (owner) calls these to release assets when a user burns their wrapped tokens on L1. If the amount exceeds largeWithdrawalThreshold, a timelock is queued instead.

Timelock

function executeTimelock(uint256 requestId) external;  // Owner, after delay
function cancelTimelock(uint256 requestId) external;    // Guardian

Large releases are queued with a configurable delay (default 24 hours). The guardian can cancel suspicious requests during the delay window.

Admin

function pause() external;                              // Guardian or Owner
function unpause() external;                             // Owner only
function setGuardian(address newGuardian) external;      // Owner
function setSupportedToken(address token, bool) external;// Owner
function setLargeWithdrawalThreshold(uint256) external;  // Owner

Events

EventDescription
BridgeDepositETHETH deposited for bridging
BridgeDepositERC20ERC-20 deposited for bridging
BridgeReleaseETHETH released to user
BridgeReleaseERC20ERC-20 released to user
TimelockQueuedLarge release queued with delay
TimelockExecutedQueued release executed
TimelockCancelledQueued release cancelled by guardian

Deployment

The contract is deployed on Base Sepolia (chain ID 84532). For mainnet, deploy with a Gnosis Safe multisig as the owner.

Bridge Relayer

The bridge relayer is an off-chain process that monitors pending withdrawals on RougeChain and executes the corresponding releases on Base Sepolia.

How It Works

  1. Polls the RougeChain node for pending ETH and XRGE withdrawals
  2. For each pending withdrawal, sends the corresponding asset on Base Sepolia
  3. Marks the withdrawal as fulfilled on the node

Running the Relayer

# Required environment variables
export CORE_API_URL="http://localhost:5101"
export BRIDGE_CUSTODY_PRIVATE_KEY="0x..."   # EVM private key for the bridge wallet
export BRIDGE_RELAYER_SECRET="your-secret"  # Shared secret for API authentication
export BASE_SEPOLIA_RPC="https://sepolia.base.org"

# Optional
export XRGE_BRIDGE_VAULT="0x..."            # BridgeVault contract address
export ROUGE_BRIDGE_ADDRESS="0x..."         # RougeBridge contract address
export USDC_ADDRESS="0x036CbD53842c5426634e7929541eC2318f3dCF7e"
export POLL_INTERVAL_MS="5000"

# Run
npx tsx scripts/bridge-relayer.ts

Authentication

The relayer authenticates with the node using the BRIDGE_RELAYER_SECRET environment variable. This is sent as the x-bridge-relayer-secret HTTP header when marking withdrawals as fulfilled.

Set the same secret on both the relayer and the node:

# On the node
export BRIDGE_RELAYER_SECRET="your-secret"

# On the relayer
export BRIDGE_RELAYER_SECRET="your-secret"

Contract Mode vs Legacy Mode

  • With ROUGE_BRIDGE_ADDRESS — The relayer calls releaseETH() / releaseERC20() on the RougeBridge contract
  • Without it — Falls back to raw ETH transfers from the custody wallet (legacy mode)
  • With XRGE_BRIDGE_VAULT — Enables XRGE bridge support via the BridgeVault contract

Security Considerations

  • The relayer's EVM private key should be stored securely (not in code)
  • Use a dedicated wallet with limited funds for the relayer
  • For production, the RougeBridge contract owner should be a multisig
  • The BRIDGE_RELAYER_SECRET should be a strong random string

DEX & AMM

RougeChain includes a built-in decentralized exchange (DEX) powered by an Automated Market Maker (AMM) using the constant product formula (x * y = k).

Overview

  • Create pools for any token pair
  • Swap between tokens with slippage protection
  • Provide liquidity and earn fees from trades
  • Multi-hop routing for tokens without direct pools

All operations are signed client-side with ML-DSA-65 — your private key never leaves the browser.

Fee Structure

OperationFee
Create Pool100 XRGE
Swap0.3% of input + 1 XRGE tx fee
Add Liquidity1 XRGE
Remove Liquidity1 XRGE

The 0.3% swap fee is distributed to liquidity providers proportional to their share of the pool.

Pool Mechanics

Pools use the Constant Product Market Maker model:

reserve_a × reserve_b = k (constant)

When a user swaps token A for token B:

  1. Token A is added to the pool
  2. Token B is removed, maintaining the constant product
  3. 0.3% fee is taken from the input amount
  4. Price impact increases with larger trades relative to pool size

LP Tokens

When you provide liquidity, you receive LP tokens representing your share of the pool. When you remove liquidity, you burn LP tokens and receive your proportional share of both tokens in the pool.

Liquidity Pools

Creating a Pool

To create a new trading pool:

  1. Go to the Swap page
  2. Click Create Pool
  3. Select two tokens (e.g., XRGE / qETH)
  4. Enter the initial amounts for each token
  5. Click Create Pool

The initial token ratio sets the starting price. A 100 XRGE fee is charged for pool creation.

Adding Liquidity

  1. Go to the pool page
  2. Click Add Liquidity
  3. Enter the amount of one token — the other amount auto-calculates based on the current ratio
  4. Confirm the transaction

You receive LP tokens proportional to your contribution.

Removing Liquidity

  1. Go to the pool page
  2. Click Remove Liquidity
  3. Enter the LP token amount to withdraw
  4. You receive your proportional share of both tokens

Impermanent Loss

If the price ratio changes significantly from when you deposited, you may experience impermanent loss compared to simply holding the tokens. This is standard AMM behavior.

Pool Stats

Each pool shows:

  • Current reserves for both tokens
  • Total LP tokens issued
  • Your LP share percentage
  • 24h volume and fees earned
  • Price history chart

Swaps

Making a Swap

  1. Go to the Swap page
  2. Select the input token and output token
  3. Enter the amount to swap
  4. Review the quote (output amount, price impact, minimum received)
  5. Click Swap

Slippage Protection

Set your maximum slippage tolerance to protect against price movements during your transaction. If the actual output would be less than your minimum, the transaction is rejected.

Default slippage: 0.5%

Price Impact

Price impact shows how much your trade will move the pool price. Large trades relative to pool size have higher price impact.

Price ImpactSeverity
< 1%Low
1-5%Medium
> 5%High (warning shown)

Multi-Hop Routing

If no direct pool exists between your tokens, the router automatically finds a path through XRGE:

TOKEN_A → XRGE → TOKEN_B

This uses two swaps internally but is handled in a single transaction.

Fees

  • 0.3% of the input amount goes to liquidity providers
  • 1 XRGE base transaction fee

Token Creation

Create custom tokens on RougeChain. Tokens can be traded on the built-in AMM/DEX.

Overview

PropertyValue
Creation fee100 XRGE
Max supplySet at creation (immutable)
DecimalsConfigurable
TradingVia AMM liquidity pools

Create a Token

Via Web UI

  1. Navigate to the Token Explorer page
  2. Click Create Token
  3. Fill in token details:
    • Name — Full name (e.g., "My Token")
    • Symbol — Ticker symbol (e.g., "MTK")
    • Total Supply — Maximum supply
    • Decimals — Decimal places (typically 8)
  4. Confirm and sign the transaction

Via v2 API

curl -X POST https://testnet.rougechain.io/api/v2/token/create \
  -H "Content-Type: application/json" \
  -d '{
    "publicKey": "your-public-key-hex",
    "payload": {
      "name": "My Token",
      "symbol": "MTK",
      "totalSupply": 1000000,
      "decimals": 8
    },
    "nonce": 1706745600000,
    "signature": "your-ml-dsa65-signature-hex"
  }'

Response

{
  "success": true,
  "txId": "abc123...",
  "token": {
    "symbol": "MTK",
    "name": "My Token",
    "totalSupply": 1000000,
    "decimals": 8,
    "creator": "your-public-key"
  }
}

After Creation

Once created, the entire supply is credited to the creator's wallet. You can then:

  1. Transfer tokens to other wallets
  2. Create a liquidity pool to enable trading
  3. Burn tokens by sending to the burn address

Creating a Liquidity Pool

To make your token tradeable on the DEX:

curl -X POST https://testnet.rougechain.io/api/v2/pool/create \
  -H "Content-Type: application/json" \
  -d '{
    "publicKey": "your-public-key-hex",
    "payload": {
      "tokenA": "XRGE",
      "tokenB": "MTK",
      "amountA": 1000,
      "amountB": 10000
    },
    "nonce": 1706745600001,
    "signature": "your-signature-hex"
  }'

This creates an XRGE/MTK pool with an initial price of 0.1 XRGE per MTK.

Pool creation costs 10 XRGE.

Token Burning

Send tokens to the burn address to permanently remove them from circulation:

XRGE_BURN_0x000000000000000000000000000000000000000000000000000000000000DEAD

Burned amounts are tracked on-chain and queryable via GET /api/burned.

Listing on the DEX

Tokens are automatically listed on the DEX once a liquidity pool is created. Users can then:

  • Swap between your token and XRGE
  • Add/remove liquidity
  • View price charts and pool stats

Token Standards

RougeChain tokens are native protocol-level assets (not smart contract tokens). This means:

  • No ERC-20 compatibility (different chain architecture)
  • Transfers are first-class transactions
  • All token operations are signed with ML-DSA-65
  • Quantum-resistant by default

NFTs

RougeChain supports on-chain NFTs with collections, minting, transfers, and marketplace features — all secured by post-quantum cryptography.

Features

  • Collections — Create NFT collections with configurable max supply, royalties, and metadata
  • Minting — Mint single or batch NFTs with metadata URIs and custom attributes
  • Transfers — Send NFTs to any RougeChain address with optional sale price tracking
  • Burning — Permanently destroy NFTs
  • Locking — Lock individual NFTs to prevent transfers
  • Freezing — Freeze entire collections to prevent further minting

Fee Structure

OperationFee (XRGE)
Create Collection50
Mint NFT5
Batch Mint5 per NFT
Transfer1
Burn0.1
Lock/Unlock0.1
Freeze Collection0.1

Security

All NFT operations use the v2 signed transaction API — transactions are signed client-side with ML-DSA-65 and verified on-chain. Only collection creators can mint, and only token owners can transfer or burn.

NFT Collections

Creating a Collection

  1. Go to the NFT Explorer page
  2. Click Create Collection
  3. Fill in:
    • Symbol — Short identifier (e.g., "ROGUE")
    • Name — Full collection name
    • Max Supply — Maximum number of NFTs (optional, 0 = unlimited)
    • Royalty — Royalty percentage in basis points (e.g., 500 = 5%)
    • Image — Collection cover image URL
    • Description — Collection description
  4. Click Create

The collection ID is generated from creator_pubkey:SYMBOL.

Collection Properties

PropertyDescription
idUnique identifier (creator:symbol)
symbolShort token symbol
nameFull collection name
creatorCreator's public key
max_supplyMax tokens (0 = unlimited)
royalty_bpsRoyalty in basis points
frozenWhether minting is frozen
total_mintedNumber of tokens minted

Freezing a Collection

Collection creators can freeze their collections to permanently prevent further minting. This is irreversible and signals to holders that the supply is final.

Browsing Collections

The NFT Explorer page shows all collections with their stats, floor price, and total items. Click any collection to view its individual tokens.

Minting & Trading NFTs

Minting

Single Mint

  1. Open a collection page
  2. Click Mint NFT
  3. Enter the token name and optional metadata URI / attributes
  4. Click Mint

Only the collection creator can mint new tokens.

Batch Mint

Mint multiple NFTs at once:

  1. Open a collection page
  2. Click Batch Mint
  3. Provide a list of names (and optional URIs/attributes for each)
  4. Click Mint All

Fee is 5 XRGE per NFT in the batch.

Token Properties

Each NFT has:

PropertyDescription
token_idSequential ID within the collection
nameToken name
ownerCurrent owner's public key
creatorOriginal minter
metadata_uriLink to off-chain metadata (IPFS, HTTP)
attributesOn-chain key-value attributes
lockedWhether the token is locked (non-transferable)
created_atTimestamp of minting

Transferring

  1. Open the NFT detail page
  2. Click Transfer
  3. Enter the recipient's RougeChain public key
  4. Optionally set a sale price (for marketplace tracking)
  5. Confirm

Locked NFTs cannot be transferred until unlocked by the owner.

Burning

Permanently destroy an NFT:

  1. Open the NFT detail page
  2. Click Burn
  3. Confirm

Only the current owner can burn. This action is irreversible.

Locking

Lock an NFT to prevent it from being transferred:

  1. Open the NFT detail page
  2. Toggle Lock

Only the owner can lock/unlock their NFTs.

Block Explorer

RougeChain includes a built-in block explorer at rougechain.io for browsing blocks, transactions, addresses, tokens, and NFTs.

Features

  • Block details — View block height, hash, timestamp, proposer, and all transactions
  • Transaction details — View transaction type, sender, recipient, amount, fee, and status
  • Address pages — View any address's balances, token holdings, and transaction history
  • Token list — Browse all tokens created on RougeChain
  • NFT Explorer — Browse NFT collections and individual tokens
  • Global search — Search by address, transaction hash, or block height

The explorer is integrated into the main RougeChain web app:

PageURLDescription
Blockchain/blockchainBlock list with live updates
Block Detail/block/:heightIndividual block
Transaction/tx/:hashIndividual transaction
Address/address/:pubkeyAddress details
Transactions/transactionsAll transactions list
NFT Explorer/nft-explorerNFT collections browser
Tokens/tokensAll tokens list

Block Explorer — Blocks

Block List

The Blockchain page shows all blocks in reverse chronological order with:

  • Block height (index)
  • Block hash (truncated)
  • Timestamp
  • Number of transactions
  • Proposer address

Click any block to view its full details.

Block Detail Page

URL: /block/:height

Shows:

FieldDescription
HeightBlock number in the chain
HashSHA-256 hash of the block
Previous HashHash of the parent block
TimestampWhen the block was created
ProposerPublic key of the block proposer
Transaction CountNumber of transactions in the block

Below the header, all transactions in the block are listed with their type, sender, recipient, amount, and fee.

API

GET /api/blocks              — List all blocks (paginated)
GET /api/block/:height       — Get a specific block by height
GET /api/blocks/summary      — Block summary for charts

Block Explorer — Transactions

Transaction List

The Transactions page shows all transactions across the network with:

  • Transaction hash
  • Type (transfer, swap, stake, bridge, NFT, etc.)
  • Sender and recipient
  • Amount
  • Block number
  • Timestamp

Transaction Detail Page

URL: /tx/:hash

Shows the full transaction details:

FieldDescription
HashTransaction hash (SHA-256)
TypeTransaction type
FromSender public key
ToRecipient public key
AmountTransaction amount
FeeTransaction fee (XRGE)
TokenToken symbol (if applicable)
BlockBlock height containing this tx
TimestampWhen the transaction was processed
SignaturePQC signature (ML-DSA-65)

Transaction Types

TypeDescription
transferToken transfer between addresses
create_tokenNew token creation
stakeStaking tokens
unstakeUnstaking tokens
create_poolCreating a liquidity pool
add_liquidityAdding liquidity to a pool
remove_liquidityRemoving liquidity from a pool
swapToken swap via AMM
bridge_mintMinting bridged tokens (qETH, qUSDC)
bridge_withdrawBurning bridged tokens for withdrawal
nft_create_collectionCreating an NFT collection
nft_mintMinting an NFT
nft_transferTransferring an NFT
nft_burnBurning an NFT

API

GET /api/txs                                    — List recent transactions
GET /api/tx/:hash                               — Get transaction by hash
GET /api/address/:public_key/transactions       — Get transactions for an address

Block Explorer — Addresses

Address Detail Page

URL: /address/:pubkey

Shows comprehensive information for any RougeChain address:

Balances

  • XRGE balance
  • All token balances (qETH, qUSDC, custom tokens)
  • Staked amount (if any)

Transaction History

Paginated list of all transactions where this address is the sender or recipient, including:

  • Transfers
  • Swaps
  • Staking operations
  • Bridge operations
  • NFT operations

NFTs Owned

List of all NFTs currently owned by this address, grouped by collection.

API

GET /api/balance/:public_key                    — XRGE balance
GET /api/balance/:public_key/:token_symbol      — Token balance
GET /api/address/:public_key/transactions       — Transaction history (paginated)
GET /api/nft/owner/:pubkey                      — NFTs owned

API Reference

The RougeChain node exposes a REST API on the configured --api-port (default: 5100).

Base URL

http://127.0.0.1:5100/api

For the public testnet:

https://testnet.rougechain.io/api

Endpoints Overview

System

EndpointMethodDescription
/api/healthGETNode health check
/api/statsGETNetwork statistics

Blockchain

EndpointMethodDescription
/api/blocksGETGet all blocks
/api/blocks/summaryGETBlock summary for charts
/api/txsGETGet transactions

Wallet

EndpointMethodDescription
/api/wallet/createPOSTCreate new wallet
/api/balance/:publicKeyGETGet balance
/api/faucetPOSTRequest testnet tokens
/api/tx/submitPOSTSubmit transaction

Staking

EndpointMethodDescription
/api/validatorsGETList validators
/api/stake/submitPOSTStake tokens
/api/unstake/submitPOSTUnstake tokens

Tokens

EndpointMethodDescription
/api/token/createPOSTCreate custom token
/api/burn-addressGETGet official burn address
/api/burnedGETGet burned token stats

AMM/DEX

EndpointMethodDescription
/api/poolsGETList liquidity pools
/api/pool/:pool_idGETGet pool details
/api/pool/:pool_id/pricesGETGet price history
/api/pool/:pool_id/eventsGETGet pool events
/api/pool/:pool_id/statsGETGet pool statistics
/api/pool/createPOSTCreate liquidity pool
/api/pool/add-liquidityPOSTAdd liquidity
/api/pool/remove-liquidityPOSTRemove liquidity
/api/swap/quotePOSTGet swap quote
/api/swap/executePOSTExecute swap

Secure v2 API (Client-Side Signing)

All v2 endpoints accept pre-signed transactions. Private keys never leave the client.

EndpointMethodDescription
/api/v2/transferPOSTTransfer tokens
/api/v2/token/createPOSTCreate token
/api/v2/pool/createPOSTCreate pool
/api/v2/pool/add-liquidityPOSTAdd liquidity
/api/v2/pool/remove-liquidityPOSTRemove liquidity
/api/v2/swap/executePOSTExecute swap
/api/v2/stakePOSTStake tokens
/api/v2/unstakePOSTUnstake tokens
/api/v2/faucetPOSTRequest faucet

P2P

EndpointMethodDescription
/api/peersGETList known peers
/api/peers/registerPOSTRegister as peer
/api/blocks/importPOSTImport block from peer
/api/tx/broadcastPOSTReceive broadcasted tx

Messenger

EndpointMethodDescription
/api/messenger/walletsGETList messenger wallets
/api/messenger/wallets/registerPOSTRegister wallet
/api/messenger/conversationsGET/POSTConversations
/api/messenger/messagesGET/POSTMessages
/api/messenger/messages/readPOSTMark message as read (self-destruct)

Mail

EndpointMethodDescription
/api/names/registerPOSTRegister a mail name
/api/names/lookupGETLook up a name's public keys
/api/names/reverseGETReverse lookup (public key → name)
/api/mail/sendPOSTSend encrypted mail
/api/mail/inboxGETGet inbox
/api/mail/sentGETGet sent mail
/api/mail/trashGETGet trashed mail
/api/mail/message/:idGETGet single mail item
/api/mail/readPOSTMark mail as read
/api/mail/movePOSTMove mail to folder
/api/mail/:idDELETEDelete mail permanently

Authentication

Some endpoints require an API key (if configured on the node):

curl -H "X-API-Key: your-api-key" https://testnet.rougechain.io/api/stats

Rate Limiting

Default limits:

  • Read endpoints: 120 requests/minute
  • Write endpoints: 30 requests/minute

Rate limit headers are included in responses:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 115

Health & Stats API

System endpoints for monitoring node status and network statistics.

Health Check

GET /api/health

Returns the node's current status.

Response

{
  "status": "ok",
  "chain_id": "rougechain-devnet-1",
  "height": 12345
}
FieldTypeDescription
statusstring"ok" if the node is healthy
chain_idstringThe chain identifier
heightnumberCurrent block height

Use Cases

  • Monitoring node uptime
  • Checking sync status (compare height with peers)
  • Load balancer health checks

Network Statistics

GET /api/stats

Returns network-wide statistics.

Response

{
  "blockHeight": 12345,
  "totalTransactions": 98765,
  "totalWallets": 432,
  "totalValidators": 15,
  "totalStaked": 150000.0,
  "totalBurned": 5000.0,
  "totalPools": 8,
  "chainId": "rougechain-devnet-1"
}
FieldTypeDescription
blockHeightnumberCurrent block height
totalTransactionsnumberTotal transactions processed
totalWalletsnumberUnique wallets on the network
totalValidatorsnumberActive validators
totalStakednumberTotal XRGE staked
totalBurnednumberTotal XRGE burned
totalPoolsnumberNumber of AMM liquidity pools
chainIdstringChain identifier

Burn Stats

GET /api/burned

Get burned token statistics.

Response

{
  "totalBurned": 5000.0,
  "burnAddress": "XRGE_BURN_0x000000000000000000000000000000000000000000000000000000000000DEAD"
}

Examples

Monitoring Script

#!/bin/bash
while true; do
  HEIGHT=$(curl -s http://127.0.0.1:5100/api/health | jq '.height')
  echo "$(date): Block height = $HEIGHT"
  sleep 10
done

Compare with Testnet

LOCAL=$(curl -s http://127.0.0.1:5100/api/health | jq '.height')
TESTNET=$(curl -s https://testnet.rougechain.io/api/health | jq '.height')
echo "Local: $LOCAL, Testnet: $TESTNET, Behind: $((TESTNET - LOCAL))"

Blocks API

Endpoints for querying block data on RougeChain.

Get Blocks

GET /api/blocks?limit=50&offset=0

Query Parameters

ParameterTypeDefaultDescription
limitnumber50Maximum blocks to return
offsetnumber0Pagination offset

Response

{
  "blocks": [
    {
      "version": 1,
      "header": {
        "version": 1,
        "chainId": "rougechain-devnet-1",
        "height": 42,
        "time": 1706745600000,
        "prevHash": "abc123...",
        "txHash": "def456...",
        "proposerPubKey": "ghi789..."
      },
      "txs": [...],
      "proposerSig": "...",
      "hash": "xyz..."
    }
  ],
  "total": 12345
}

Block Fields

FieldTypeDescription
versionnumberBlock format version
header.heightnumberBlock number
header.timenumberTimestamp (ms since epoch)
header.prevHashstringHash of previous block
header.txHashstringMerkle root of transactions
header.proposerPubKeystringValidator who proposed this block
txsarrayTransactions included in this block
proposerSigstringML-DSA-65 signature by the proposer
hashstringSHA-256 hash of this block

Block Summary

GET /api/blocks/summary

Returns a lightweight summary of recent blocks, suitable for charts and dashboards.

Response

{
  "blocks": [
    {
      "height": 42,
      "time": 1706745600000,
      "txCount": 5,
      "proposer": "abc123..."
    }
  ]
}

Import Block (P2P)

Used by peer nodes to propagate blocks.

POST /api/blocks/import
Content-Type: application/json

See Peers API for details.


Block Verification

Every block is verified by receiving nodes:

  1. Hash check — Recompute the block hash and compare
  2. Signature check — Verify ML-DSA-65 signature against the proposer's public key
  3. Height check — Must extend the current chain tip by exactly 1
  4. Previous hash — Must reference the current tip's hash
  5. Transaction validity — All transactions must have valid signatures and sufficient balances

Transactions API

Submit Transaction

Send XRGE tokens to another address.

POST /api/tx/submit
Content-Type: application/json

Request Body

{
  "fromPrivateKey": "your-private-key-hex",
  "fromPublicKey": "your-public-key-hex", 
  "toPublicKey": "recipient-public-key-hex",
  "amount": 100.0,
  "fee": 0.1
}
FieldTypeRequiredDescription
fromPrivateKeystringYesSender's ML-DSA-65 private key (hex)
fromPublicKeystringYesSender's ML-DSA-65 public key (hex)
toPublicKeystringYesRecipient's public key (hex)
amountnumberYesAmount of XRGE to send
feenumberNoTransaction fee (default: 0.1)

Response

{
  "success": true,
  "txId": "abc123...",
  "tx": {
    "version": 1,
    "txType": "transfer",
    "fromPubKey": "...",
    "nonce": 1234567890,
    "payload": {
      "toPubKeyHex": "...",
      "amount": 100
    },
    "fee": 0.1,
    "sig": "..."
  }
}

Error Response

{
  "success": false,
  "error": "insufficient balance: have 50.0000 XRGE, need 100.1000 XRGE"
}

Get Transactions

Retrieve recent transactions.

GET /api/txs?limit=50&offset=0

Query Parameters

ParameterTypeDefaultDescription
limitnumber50Max transactions to return
offsetnumber0Pagination offset

Response

{
  "txs": [
    {
      "version": 1,
      "txType": "transfer",
      "fromPubKey": "abc...",
      "nonce": 1234567890,
      "payload": {
        "toPubKeyHex": "def...",
        "amount": 100
      },
      "fee": 0.1,
      "sig": "ghi...",
      "blockHeight": 42,
      "blockTime": 1706745600000
    }
  ],
  "total": 150
}

Request Faucet (Testnet)

Get free testnet XRGE tokens.

POST /api/faucet
Content-Type: application/json

Request Body

{
  "publicKey": "your-public-key-hex"
}

Response

{
  "success": true,
  "amount": 1000,
  "txId": "abc123..."
}

Rate Limit

The faucet has additional rate limiting:

  • 1 request per address per hour
  • Whitelisted addresses bypass rate limits

Transaction Types

TypeDescription
transferStandard XRGE transfer
faucetFaucet distribution
stakeStake tokens to become validator
unstakeUnstake tokens
create_tokenCreate custom token

Wallet API

Endpoints for wallet creation, balance queries, and token management.

Get Balance

GET /api/balance/:publicKey

Path Parameters

ParameterTypeDescription
publicKeystringThe wallet's ML-DSA-65 public key (hex)

Response

{
  "balance": 1500.5,
  "publicKey": "abc123...",
  "tokens": {
    "XRGE": 1500.5,
    "qETH": 0.5
  }
}

Create Wallet

POST /api/wallet/create

Creates a new wallet on the server. In practice, wallets are created client-side and only need to interact with the chain when transacting.

Response

{
  "success": true,
  "publicKey": "abc123...",
  "privateKey": "def456..."
}

Note: The v2 API uses client-side key generation. Private keys never leave the browser. This endpoint exists for legacy compatibility.


Request Faucet

POST /api/faucet
Content-Type: application/json

Request Body

{
  "publicKey": "your-public-key-hex"
}

Response

{
  "success": true,
  "amount": 1000,
  "txId": "abc123..."
}

See Get Test Tokens for details on rate limits.


Submit Transaction (Legacy)

POST /api/tx/submit
Content-Type: application/json

See Transactions API for full details.


v2 Transfer (Client-Side Signing)

POST /api/v2/transfer
Content-Type: application/json

Request Body

{
  "publicKey": "sender-public-key-hex",
  "payload": {
    "toPubKeyHex": "recipient-public-key-hex",
    "amount": 100,
    "fee": 0.1,
    "token": "XRGE"
  },
  "nonce": 1706745600000,
  "signature": "ml-dsa65-signature-hex"
}

The transaction is signed client-side using ML-DSA-65. The server verifies the signature before processing.

Response

{
  "success": true,
  "txId": "abc123..."
}

v2 Faucet

POST /api/v2/faucet
Content-Type: application/json

Request Body

{
  "publicKey": "your-public-key-hex",
  "nonce": 1706745600000,
  "signature": "your-signature-hex"
}

Response

{
  "success": true,
  "amount": 1000,
  "txId": "abc123..."
}

Burn Address

GET /api/burn-address

Response

{
  "burnAddress": "XRGE_BURN_0x000000000000000000000000000000000000000000000000000000000000DEAD"
}

Send tokens to this address to permanently burn them. Burned amounts are tracked on-chain.

Staking API

Endpoints for validator staking operations.

List Validators

GET /api/validators

Query Parameters

ParameterTypeDescription
publicKeystring(Optional) Filter by specific validator

Response

{
  "validators": [
    {
      "publicKey": "abc123...",
      "stake": 10000.0,
      "status": "active",
      "blocksProposed": 142
    },
    {
      "publicKey": "def456...",
      "stake": 5000.0,
      "status": "active",
      "blocksProposed": 71
    }
  ],
  "totalStaked": 15000.0
}

Validator Fields

FieldTypeDescription
publicKeystringValidator's ML-DSA-65 public key
stakenumberAmount of XRGE staked
statusstringactive or unbonding
blocksProposednumberTotal blocks produced

Stake Tokens

Legacy API

POST /api/stake/submit
Content-Type: application/json
{
  "fromPrivateKey": "your-private-key-hex",
  "fromPublicKey": "your-public-key-hex",
  "amount": 1000
}

v2 API (Client-Side Signing)

POST /api/v2/stake
Content-Type: application/json
{
  "publicKey": "your-public-key-hex",
  "payload": {
    "amount": 1000
  },
  "nonce": 1706745600000,
  "signature": "your-ml-dsa65-signature-hex"
}

Response

{
  "success": true,
  "txId": "abc123...",
  "stake": 1000.0,
  "status": "active"
}

Requirements

RequirementValue
Minimum stake1,000 XRGE
Fee0.1 XRGE

Unstake Tokens

Legacy API

POST /api/unstake/submit
Content-Type: application/json
{
  "fromPrivateKey": "your-private-key-hex",
  "fromPublicKey": "your-public-key-hex",
  "amount": 500
}

v2 API (Client-Side Signing)

POST /api/v2/unstake
Content-Type: application/json
{
  "publicKey": "your-public-key-hex",
  "payload": {
    "amount": 500
  },
  "nonce": 1706745600000,
  "signature": "your-ml-dsa65-signature-hex"
}

Response

{
  "success": true,
  "txId": "abc123...",
  "remainingStake": 500.0
}

Unbonding

After unstaking, tokens enter an unbonding period (~7 days on testnet) before they become available in your balance.


Error Responses

ErrorCause
"insufficient balance"Not enough XRGE to stake
"below minimum stake"Amount is less than 1,000 XRGE
"validator not found"Trying to unstake but not a validator
"invalid signature"ML-DSA-65 signature verification failed

Peers API

Endpoints for P2P peer management and discovery.

List Peers

Get all known peers.

GET /api/peers

Response

{
  "peers": [
    "https://testnet.rougechain.io/api",
    "https://node2.example.com/api"
  ],
  "count": 2
}

Register Peer

Register this node with another peer (enables discovery).

POST /api/peers/register
Content-Type: application/json

Request Body

{
  "peerUrl": "https://mynode.example.com"
}

Response

{
  "success": true,
  "message": "Peer registered"
}

If the peer is already known:

{
  "success": true,
  "message": "Peer already known"
}

Import Block (P2P)

Receive a block from a peer (used for block propagation).

POST /api/blocks/import
Content-Type: application/json

Request Body

The full block object:

{
  "version": 1,
  "header": {
    "version": 1,
    "chainId": "rougechain-devnet-1",
    "height": 42,
    "time": 1706745600000,
    "prevHash": "abc123...",
    "txHash": "def456...",
    "proposerPubKey": "..."
  },
  "txs": [...],
  "proposerSig": "...",
  "hash": "..."
}

Response

{
  "success": true
}

Error Response

{
  "success": false,
  "error": "Block height 42 doesn't extend tip height 40"
}

Broadcast Transaction (P2P)

Receive a transaction broadcast from a peer.

POST /api/tx/broadcast
Content-Type: application/json

Request Body

The full transaction object.

Response

{
  "success": true
}

Peer Discovery Flow

1. Node A starts with --peers "https://seed.example.com"

2. Node A calls GET /api/peers on seed node
   → Receives list of other peers

3. Node A adds new peers to its list

4. If Node A has --public-url, it calls POST /api/peers/register
   on all known peers to announce itself

5. Every 30 seconds, repeat steps 2-4

This creates a mesh network where all nodes eventually discover each other.

Messenger API

Endpoints for the end-to-end encrypted PQC messenger.

All messages are encrypted client-side using ML-KEM-768 key encapsulation and AES-GCM. The server only stores encrypted blobs — it cannot read message contents.

Register Messenger Wallet

POST /api/messenger/wallets/register
Content-Type: application/json

Register your wallet's encryption public key so others can send you messages.

Request Body

{
  "publicKey": "signing-public-key-hex",
  "encPublicKey": "ml-kem768-public-key-hex",
  "displayName": "Alice"
}

Response

{
  "success": true
}

List Messenger Wallets

GET /api/messenger/wallets

Returns all registered messenger wallets.

Response

{
  "wallets": [
    {
      "publicKey": "abc123...",
      "encPublicKey": "def456...",
      "displayName": "Alice"
    }
  ]
}

Send Message

POST /api/messenger/messages
Content-Type: application/json

Request Body

{
  "conversationId": "conv-uuid",
  "senderPublicKey": "sender-pub-hex",
  "recipientPublicKey": "recipient-pub-hex",
  "senderEncrypted": "base64-encrypted-for-sender",
  "recipientEncrypted": "base64-encrypted-for-recipient",
  "senderDisplayName": "Alice",
  "recipientDisplayName": "Bob",
  "selfDestruct": false,
  "destructSeconds": 0
}

Messages are encrypted twice — once for the sender (so they can read their sent messages) and once for the recipient. The server stores both ciphertexts.

Self-Destruct Messages

Set selfDestruct: true and destructSeconds to a value. After the recipient reads the message, it is marked as read and hidden from the UI.

Response

{
  "success": true,
  "messageId": "msg-uuid"
}

Get Messages

GET /api/messenger/messages?conversationId=conv-uuid&publicKey=your-pub-hex

Query Parameters

ParameterTypeDescription
conversationIdstringThe conversation ID
publicKeystringYour public key (to get your encrypted copy)

Response

{
  "messages": [
    {
      "id": "msg-uuid",
      "conversationId": "conv-uuid",
      "senderPublicKey": "abc...",
      "senderDisplayName": "Alice",
      "encrypted": "base64-ciphertext",
      "timestamp": 1706745600000,
      "selfDestruct": false,
      "mediaType": null
    }
  ]
}

Mark Message as Read

POST /api/messenger/messages/read
Content-Type: application/json

Used for self-destruct messages.

{
  "messageId": "msg-uuid"
}

Get Conversations

GET /api/messenger/conversations?publicKey=your-pub-hex

Returns all conversations for a wallet.

Response

{
  "conversations": [
    {
      "conversationId": "conv-uuid",
      "participants": [
        {
          "publicKey": "abc...",
          "displayName": "Alice"
        },
        {
          "publicKey": "def...",
          "displayName": "Bob"
        }
      ],
      "lastMessage": "2024-01-31T12:00:00Z",
      "unreadCount": 2
    }
  ]
}

Media Messages

The messenger supports image and video attachments. Media is encrypted and sent as base64 within the message payload.

LimitValue
Max upload size50 MB (before compression)
Compressed target~1.5 MB
Image formatConverted to WebP client-side
Video formatConverted to WebM (VP9) client-side

The client automatically compresses large media before encryption and sending.


Encryption Flow

Sender                                    Recipient
  │                                          │
  │ 1. Generate shared secret via ML-KEM-768 │
  │ 2. Derive AES-256 key via HKDF           │
  │ 3. Encrypt message with AES-GCM          │
  │ 4. Encrypt for self (sender copy)        │
  │ 5. Encrypt for recipient                 │
  │                                          │
  │── POST /messages (both ciphertexts) ────►│
  │                                          │
  │                    6. Decapsulate shared secret
  │                    7. Derive same AES key
  │                    8. Decrypt message

Wallet Blocking

Users can block wallets client-side. Blocked wallets are filtered from conversations and contacts. The block list is stored in browser localStorage under pqc_blocked_wallets.

This is a client-side feature — the server is not involved. Blocked users can still send messages, but they won't appear in the blocking user's UI.

Mail API

Endpoints for the PQC-encrypted mail system. Mail uses the same ML-KEM-768 encryption as the messenger but adds subject lines, folders, threading, and a name registry.

Name Registry

Register a Name

POST /api/names/register
Content-Type: application/json

Register a human-readable email address (e.g., alice@rouge.quant).

{
  "name": "alice",
  "publicKey": "your-signing-public-key-hex",
  "encPublicKey": "your-ml-kem768-public-key-hex"
}

Response

{
  "success": true,
  "address": "alice@rouge.quant"
}

Error

{
  "success": false,
  "error": "Name already taken"
}

Lookup a Name

GET /api/names/lookup?name=alice

Response

{
  "name": "alice",
  "publicKey": "abc123...",
  "encPublicKey": "def456..."
}

Reverse Lookup (Public Key to Name)

GET /api/names/reverse?publicKey=abc123...

Response

{
  "name": "alice",
  "publicKey": "abc123..."
}

Send Mail

POST /api/mail/send
Content-Type: application/json

Request Body

{
  "from": "alice",
  "fromPublicKey": "sender-pub-hex",
  "to": "bob",
  "toPublicKey": "recipient-pub-hex",
  "senderEncrypted": "base64-encrypted-for-sender",
  "recipientEncrypted": "base64-encrypted-for-recipient",
  "replyToId": null
}

The senderEncrypted and recipientEncrypted fields contain the encrypted subject and body. Both sender and recipient get their own copy, just like the messenger.

Set replyToId to the ID of the mail being replied to, enabling threading.

Response

{
  "success": true,
  "id": "mail-uuid"
}

Get Inbox

GET /api/mail/inbox?publicKey=your-pub-hex

Response

{
  "mail": [
    {
      "id": "mail-uuid",
      "from": "alice",
      "fromPublicKey": "abc...",
      "to": "bob",
      "toPublicKey": "def...",
      "encrypted": "base64-ciphertext",
      "timestamp": 1706745600000,
      "read": false,
      "replyToId": null
    }
  ]
}

Get Sent Mail

GET /api/mail/sent?publicKey=your-pub-hex

Same response format as inbox, but returns mail you sent.


Get Single Mail

GET /api/mail/message/:id?publicKey=your-pub-hex

Mark as Read

POST /api/mail/read
Content-Type: application/json
{
  "id": "mail-uuid"
}

Move to Trash

POST /api/mail/move
Content-Type: application/json
{
  "id": "mail-uuid",
  "folder": "trash"
}

Get Trash

GET /api/mail/trash?publicKey=your-pub-hex

Delete Mail

DELETE /api/mail/:id

Permanently deletes a mail item.


Email Domains

DomainPlatform
@rouge.quantWebsite and browser extensions
@qwalla.mailQWalla mobile app (future)

Threading

Mail threading is handled client-side by following the replyToId chain. When viewing a mail, the client:

  1. Fetches both inbox and sent mail
  2. Walks the replyToId chain to build the thread
  3. Displays messages in chronological order
  4. Collapses older messages, expands the latest two

Encryption

Mail uses the same encryption as the messenger:

  1. Look up recipient's ML-KEM-768 public key via Name Registry
  2. Encapsulate a shared secret
  3. Derive AES-256 key via HKDF
  4. Encrypt subject + body with AES-GCM
  5. Create separate ciphertext for sender and recipient
  6. Server stores both encrypted copies

API Reference — Bridge

ETH/USDC Bridge

Get Bridge Config

GET /api/bridge/config

Returns bridge status, custody address, chain ID, and supported tokens.

Response:

{
  "enabled": true,
  "custodyAddress": "0x...",
  "chainId": 84532,
  "supportedTokens": ["ETH", "USDC"]
}

Claim Bridge Deposit

POST /api/bridge/claim

Claim wrapped tokens (qETH or qUSDC) after depositing on Base Sepolia.

Body:

{
  "evmTxHash": "0x...",
  "evmAddress": "0x...",
  "evmSignature": "0x...",
  "recipientRougechainPubkey": "abc123...",
  "token": "ETH"
}

The token field can be "ETH" (default) or "USDC". The node verifies the EVM transaction, checks the signature, and mints the corresponding wrapped token.

Bridge Withdraw

POST /api/bridge/withdraw

Burn wrapped tokens and create a pending withdrawal for the relayer.

Body (signed):

{
  "fromPublicKey": "abc123...",
  "amountUnits": 10000,
  "evmAddress": "0x...",
  "signature": "...",
  "payload": { "type": "bridge_withdraw", "..." }
}

List Pending Withdrawals

GET /api/bridge/withdrawals

Returns all pending ETH/USDC withdrawals waiting for the relayer.

Fulfill Withdrawal

DELETE /api/bridge/withdrawals/:txId

Mark a withdrawal as fulfilled. Requires x-bridge-relayer-secret header or a PQC-signed body.


XRGE Bridge

Get XRGE Bridge Config

GET /api/bridge/xrge/config

Response:

{
  "enabled": true,
  "vaultAddress": "0x...",
  "tokenAddress": "0x147120faEC9277ec02d957584CFCD92B56A24317",
  "chainId": 84532
}

Claim XRGE Deposit

POST /api/bridge/xrge/claim

Body:

{
  "evmTxHash": "0x...",
  "evmAddress": "0x...",
  "amount": "1000000000000000000",
  "recipientRougechainPubkey": "abc123..."
}

XRGE Withdraw

POST /api/bridge/xrge/withdraw

Body (signed):

{
  "fromPublicKey": "abc123...",
  "amount": 100,
  "evmAddress": "0x...",
  "signature": "...",
  "payload": { "..." }
}

List XRGE Withdrawals

GET /api/bridge/xrge/withdrawals

Fulfill XRGE Withdrawal

DELETE /api/bridge/xrge/withdrawals/:txId

API Reference — NFTs

All write operations use the v2 signed transaction API (client-side signing).

Read Endpoints

List Collections

GET /api/nft/collections

Get Collection

GET /api/nft/collection/:id

Get Collection Tokens

GET /api/nft/collection/:id/tokens

Get Token

GET /api/nft/token/:collection_id/:token_id

Get NFTs by Owner

GET /api/nft/owner/:pubkey

Write Endpoints (v2 Signed)

All write endpoints accept a signed transaction body:

{
  "payload": { "type": "nft_mint", "..." },
  "signature": "...",
  "public_key": "..."
}

Create Collection

POST /api/v2/nft/collection/create

Payload fields: symbol, name, maxSupply, royaltyBps, image, description Fee: 50 XRGE

Mint NFT

POST /api/v2/nft/mint

Payload fields: collectionId, name, metadataUri, attributes Fee: 5 XRGE

Batch Mint

POST /api/v2/nft/batch-mint

Payload fields: collectionId, names, uris, batchAttributes Fee: 5 XRGE per NFT

Transfer NFT

POST /api/v2/nft/transfer

Payload fields: collectionId, tokenId, to, salePrice Fee: 1 XRGE

Burn NFT

POST /api/v2/nft/burn

Payload fields: collectionId, tokenId Fee: 0.1 XRGE

Lock/Unlock NFT

POST /api/v2/nft/lock

Payload fields: collectionId, tokenId, locked Fee: 0.1 XRGE

Freeze Collection

POST /api/v2/nft/freeze-collection

Payload fields: collectionId, frozen Fee: 0.1 XRGE

API Reference — DEX / AMM

Read Endpoints

List Pools

GET /api/pools

Returns all liquidity pools with reserves, LP supply, and token info.

Get Pool

GET /api/pool/:pool_id

Pool ID format: TOKEN_A-TOKEN_B (alphabetically sorted).

Get Pool Events

GET /api/pool/:pool_id/events

Returns swap, add_liquidity, and remove_liquidity events for a pool.

Get Pool Price History

GET /api/pool/:pool_id/prices

Get Pool Stats

GET /api/pool/:pool_id/stats

Get Swap Quote

POST /api/swap/quote

Body:

{
  "tokenIn": "XRGE",
  "tokenOut": "qETH",
  "amountIn": 1000
}

Response:

{
  "amountOut": 95,
  "priceImpact": 0.5,
  "fee": 3,
  "route": ["XRGE", "qETH"]
}

Get All Events

GET /api/events

Returns all DEX events across all pools.

Write Endpoints (v2 Signed)

Create Pool

POST /api/v2/pool/create

Payload fields: token_a, token_b, amount_a, amount_b Fee: 100 XRGE

Add Liquidity

POST /api/v2/pool/add-liquidity

Payload fields: pool_id, amount_a, amount_b Fee: 1 XRGE

Remove Liquidity

POST /api/v2/pool/remove-liquidity

Payload fields: pool_id, lp_amount Fee: 1 XRGE

Execute Swap

POST /api/v2/swap/execute

Payload fields: token_in, token_out, amount_in, min_amount_out Fee: 0.3% of input + 1 XRGE

Architecture

An overview of RougeChain's system architecture.

High-Level Architecture

┌───────────────────────────────────────────────────────────┐
│                      Clients                               │
│                                                           │
│  ┌──────────┐  ┌──────────────────┐  ┌────────────────┐  │
│  │ Website  │  │ Browser Extension│  │ @rougechain/sdk│  │
│  │ React    │  │ Chrome / Firefox │  │ npm package    │  │
│  └────┬─────┘  └────────┬─────────┘  └───────┬────────┘  │
│       │                 │                     │           │
│       │   Client-side ML-DSA-65 signing       │           │
│       │   Client-side ML-KEM-768 encryption   │           │
│       └────────────┬────┴─────────────────────┘           │
└────────────────────┼──────────────────────────────────────┘
                     │ HTTPS REST API
                     ▼
┌───────────────────────────────────────────────────────────┐
│                   Core Node (Rust)                        │
│                                                           │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
│  │ REST API │  │Blockchain│  │Validator │  │Messenger │ │
│  │ (Actix)  │  │ Engine   │  │ / PoS    │  │ Server   │ │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘ │
│       │              │              │              │       │
│  ┌────┴──────────────┴──────────────┴──────────────┴────┐ │
│  │                    Storage Layer                      │ │
│  │  chain.jsonl │ validators-db (RocksDB) │ messenger-db│ │
│  └──────────────────────────────────────────────────────┘ │
└────────────────────┬──────────────────────────────────────┘
                     │ P2P (HTTP)
                     ▼
┌───────────────────────────────────────────────────────────┐
│                    Peer Nodes                             │
│         Block sync │ TX broadcast │ Peer discovery        │
└───────────────────────────────────────────────────────────┘

Components

Core Node (Rust)

The backend is a single Rust binary (quantum-vault-daemon) that includes:

ModuleResponsibility
REST APIHTTP endpoints via Actix-web
Blockchain EngineBlock production, transaction processing, state management
Validator / PoSStake tracking, proposer selection, rewards
Messenger ServerStores encrypted messages and wallet registrations
Mail ServerStores encrypted mail, name registry
P2P LayerPeer discovery, block/tx propagation
AMM/DEXLiquidity pools, swap execution, price calculation
BridgeqETH bridge from Base Sepolia

Frontend (React + TypeScript)

The website at rougechain.io is a single-page application built with:

TechnologyPurpose
React 18UI framework
TypeScriptType safety
ViteBuild tool
Tailwind CSSStyling
shadcn/uiComponent library
@noble/post-quantumPQC cryptography (ML-DSA-65, ML-KEM-768)

The frontend is a PWA (Progressive Web App) and can be installed on mobile and desktop.

Browser Extensions

Two Chrome extensions provide wallet functionality:

ExtensionDescription
RougeChain WalletPrimary browser extension
rougechain-walletSecondary extension

Both inject a window.rougechain provider (similar to MetaMask's window.ethereum) for dApp integration.

SDK (@rougechain/sdk)

The npm package @rougechain/sdk provides a programmatic interface for interacting with RougeChain from Node.js or browser applications.

Cryptography Stack

┌─────────────────────────────────────────┐
│            Application Layer            │
│  Transactions │ Messages │ Mail │ Auth  │
└─────────────┬───────────────────────────┘
              │
┌─────────────▼───────────────────────────┐
│         Cryptographic Primitives        │
│                                         │
│  ML-DSA-65 (FIPS 204)                  │
│  └─ Signing: txs, blocks, stakes       │
│                                         │
│  ML-KEM-768 (FIPS 203)                 │
│  └─ Key encapsulation: messenger, mail │
│                                         │
│  AES-256-GCM                           │
│  └─ Symmetric encryption of content    │
│                                         │
│  HKDF (SHA-256)                        │
│  └─ Key derivation from shared secrets │
│                                         │
│  SHA-256                               │
│  └─ Block hashes, tx hashes, Merkle   │
└─────────────────────────────────────────┘

Data Flow

Transaction Flow

1. User creates transaction in browser
2. Transaction payload is constructed
3. ML-DSA-65 signs the payload client-side
4. Signed transaction is sent to node via REST API
5. Node verifies signature
6. Transaction enters mempool
7. Validator includes it in next block
8. Block is signed and propagated to peers

Message Flow

1. Sender looks up recipient's ML-KEM-768 public key
2. ML-KEM-768 encapsulation generates shared secret
3. HKDF derives AES-256 key from shared secret
4. Message is encrypted with AES-GCM (for both sender and recipient)
5. Encrypted blobs are sent to server
6. Recipient fetches encrypted blob
7. ML-KEM-768 decapsulation recovers shared secret
8. Message is decrypted client-side

Mail Flow

1. User registers a name (e.g., alice@rouge.quant) via Name Registry
2. Sender composes email, encrypts subject + body with PQC
3. Encrypted mail is stored on the server
4. Recipient fetches and decrypts client-side
5. Thread history is reconstructed via replyToId chain

Storage

Node Storage

StoreFormatContent
chain.jsonlAppend-only JSON linesBlock data
tip.jsonJSONCurrent chain tip reference
validators-db/RocksDBValidator stakes and state
messenger-db/RocksDBEncrypted messages and wallets

Client Storage

StoreLocationContent
Wallet keyslocalStorageEncrypted ML-DSA-65 and ML-KEM-768 keys
Block listlocalStorageBlocked wallet addresses
Mail settingslocalStorageEmail signature preferences
Display namelocalStorageUser's messenger display name

Security Model

PrincipleImplementation
Keys never leave clientAll signing/encryption happens in-browser
Server is untrustedServer only stores encrypted data
Quantum-resistantNIST-approved PQC algorithms throughout
No seed phrasesKeys are stored directly (backup via file export)
Dual encryptionMessages encrypted for both sender and recipient

Post-Quantum Cryptography

RougeChain uses NIST-approved post-quantum cryptographic algorithms to protect against both classical and quantum computer attacks.

Why Post-Quantum?

Quantum computers threaten current cryptography:

AlgorithmQuantum Threat
RSABroken by Shor's algorithm
ECDSABroken by Shor's algorithm
SHA-256Weakened (Grover's algorithm)
ML-DSASecure
ML-KEMSecure

Algorithms Used

ML-DSA-65 (Digital Signatures)

Formerly: CRYSTALS-Dilithium
Standard: FIPS 204
Security Level: NIST Level 3 (192-bit classical equivalent)

Used for:

  • Transaction signatures
  • Block proposal signatures
  • Validator attestations

Key sizes:

ComponentSize
Public key~1,952 bytes
Private key~4,032 bytes
Signature~3,309 bytes

ML-KEM-768 (Key Encapsulation)

Formerly: CRYSTALS-Kyber
Standard: FIPS 203
Security Level: NIST Level 3

Used for:

  • Messenger encryption
  • PQC Mail encryption
  • Future: Encrypted transactions

Key sizes:

ComponentSize
Public key~1,184 bytes
Private key~2,400 bytes
Ciphertext~1,088 bytes

SHA-256 (Hashing)

Used for:

  • Block hashes
  • Transaction hashes
  • Merkle trees

While Grover's algorithm reduces SHA-256 security to ~128-bit equivalent against quantum computers, this is still considered secure.

Implementation

RougeChain uses the following libraries:

ComponentLibrary
Backend (Rust)pqcrypto crate
Frontend (JS)@noble/post-quantum

All cryptographic operations happen locally - private keys never leave your device.

Key Generation

#![allow(unused)]
fn main() {
// Rust example
use pqcrypto_dilithium::dilithium3::*;

let (pk, sk) = keypair();
let signature = sign(message, &sk);
let valid = verify(message, &signature, &pk);
}
// TypeScript example
import { ml_dsa65 } from '@noble/post-quantum/ml-dsa';

const { publicKey, secretKey } = ml_dsa65.keygen();
const signature = ml_dsa65.sign(message, secretKey);
const valid = ml_dsa65.verify(signature, message, publicKey);

Security Considerations

  1. Key storage - Private keys are stored in browser localStorage (encrypted in production)
  2. Entropy - Keys use cryptographically secure random number generators
  3. Side channels - Library implementations are designed to be constant-time
  4. Hybrid approach - Consider adding classical signatures for defense-in-depth

Future Roadmap

  • SLH-DSA (SPHINCS+) as alternative signature scheme
  • Hybrid classical+PQC mode
  • Hardware wallet support
  • Threshold signatures for multi-sig

Browser Extensions

RougeChain provides browser extensions that serve as quantum-safe wallets, similar to how MetaMask works for Ethereum — but using post-quantum cryptography.

Available Extensions

ExtensionDescriptionStore
RougeChain WalletPrimary browser extensionChrome Web Store
rougechain-walletSecondary extensionChrome Web Store

Features

  • Wallet — View balances, send/receive XRGE, claim faucet, custom token support
  • Encrypted Messenger — E2E encrypted chat using ML-KEM-768 + ML-DSA-65
  • PQC Mail — Encrypted email with @rouge.quant addresses
  • Vault Lock — AES-256-GCM encryption with PBKDF2 key derivation and auto-lock timer
  • Cross-browser — Chrome, Edge, Brave, Opera, Arc, Firefox (Manifest V3)

Installation

From Chrome Web Store

  1. Visit the extension page on the Chrome Web Store
  2. Click Add to Chrome
  3. The extension icon appears in your toolbar

From Source

cd browser-extension
npm install
npm run build
  1. Open chrome://extensions (or edge://extensions, brave://extensions)
  2. Enable Developer mode
  3. Click Load unpacked
  4. Select the browser-extension/dist folder

Firefox

cd browser-extension
npm install
npm run build
  1. Open about:debugging#/runtime/this-firefox
  2. Click Load Temporary Add-on
  3. Select browser-extension/dist/manifest.json

DApp Integration

The extension injects a window.rougechain provider object, similar to MetaMask's window.ethereum. DApps can use this to interact with the user's wallet.

Detecting the Extension

if (window.rougechain) {
  console.log('RougeChain wallet detected');
  const address = await window.rougechain.getAddress();
}

Provider API

MethodDescription
getAddress()Get the user's public key
signTransaction(tx)Sign a transaction with ML-DSA-65
getBalance()Get the wallet's balance
getNetwork()Get the current network (testnet/devnet)

Security

FeatureImplementation
Vault encryptionAES-256-GCM with PBKDF2-derived key
Auto-lockConfigurable timer via background service worker
Key storagechrome.storage.local (encrypted)
SigningML-DSA-65 (FIPS 204) — quantum-resistant
EncryptionML-KEM-768 (FIPS 203) — quantum-resistant

Permissions

The extensions request minimal permissions:

PermissionPurpose
storageStore encrypted wallet data
alarmsAuto-lock timer
notificationsTransaction alerts
Host permissionsConnect to RougeChain nodes (rougechain.io, testnet.rougechain.io, localhost)

Why Not MetaMask?

MetaMask and all EVM wallets use secp256k1 / ECDSA cryptography. RougeChain uses ML-DSA-65 / ML-KEM-768 (post-quantum). The key formats, signature schemes, and transaction structures are fundamentally incompatible. RougeChain's extensions are purpose-built for quantum-safe operations.

See PQC Cryptography for details on the algorithms used.

SDK (@rougechain/sdk)

The official JavaScript/TypeScript SDK for building on RougeChain.

Installation

npm install @rougechain/sdk

Quick Start

import { RougeChain, Wallet } from '@rougechain/sdk';

const rc = new RougeChain('https://testnet.rougechain.io/api');

// Generate a new post-quantum wallet
const wallet = Wallet.generate();
console.log('Public key:', wallet.publicKey);

// Request testnet tokens
await rc.faucet(wallet);

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

// Transfer tokens
await rc.transfer(wallet, { to: recipientPubKey, amount: 100 });

Wallet

All signing happens client-side. Private keys never leave your application.

import { Wallet } from '@rougechain/sdk';

// Generate new keypair
const wallet = Wallet.generate();

// Restore from saved keys
const restored = Wallet.fromKeys(publicKey, privateKey);

// Export for storage
const keys = wallet.toJSON(); // { publicKey, privateKey }

// Verify keypair integrity
const valid = wallet.verify(); // true

Client

import { RougeChain } from '@rougechain/sdk';

// Basic connection
const rc = new RougeChain('https://testnet.rougechain.io/api');

// With API key
const rc = new RougeChain('https://testnet.rougechain.io/api', {
  apiKey: 'your-api-key',
});

Available Methods

Queries

await rc.getHealth();
await rc.getStats();
await rc.getBlocks({ limit: 10 });
await rc.getBalance(publicKey);
await rc.getValidators();
await rc.getTokens();
await rc.getBurnedTokens();

Transactions

await rc.transfer(wallet, { to: recipient, amount: 100 });
await rc.transfer(wallet, { to: recipient, amount: 50, token: 'MYTOKEN' });
await rc.createToken(wallet, { name: 'My Token', symbol: 'MTK', totalSupply: 1_000_000 });
await rc.burn(wallet, 500, 1, 'XRGE');
await rc.faucet(wallet);

Staking

await rc.stake(wallet, { amount: 1000 });
await rc.unstake(wallet, { amount: 500 });

DEX (rc.dex)

await rc.dex.getPools();
await rc.dex.getPool('XRGE-MTK');
await rc.dex.quote({ poolId: 'XRGE-MTK', tokenIn: 'XRGE', amountIn: 100 });
await rc.dex.swap(wallet, { tokenIn: 'XRGE', tokenOut: 'MTK', amountIn: 100, minAmountOut: 95 });
await rc.dex.createPool(wallet, { tokenA: 'XRGE', tokenB: 'MTK', amountA: 10000, amountB: 5000 });
await rc.dex.addLiquidity(wallet, { poolId: 'XRGE-MTK', amountA: 1000, amountB: 500 });
await rc.dex.removeLiquidity(wallet, { poolId: 'XRGE-MTK', lpAmount: 100 });

NFTs (rc.nft)

await rc.nft.createCollection(wallet, { symbol: 'ART', name: 'My Art', royaltyBps: 500, maxSupply: 10000 });
await rc.nft.mint(wallet, { collectionId: 'abc123', name: 'Piece #1', metadataUri: '...' });
await rc.nft.batchMint(wallet, { collectionId: 'abc123', names: ['#1', '#2'], uris: ['...', '...'] });
await rc.nft.transfer(wallet, { collectionId: 'abc123', tokenId: 1, to: buyerPubKey, salePrice: 100 });
await rc.nft.getCollections();
await rc.nft.getByOwner(wallet.publicKey);

Bridge (rc.bridge)

await rc.bridge.getConfig();
await rc.bridge.withdraw(wallet, { amount: 500000, evmAddress: '0x...' });
await rc.bridge.claim({ evmTxHash: '0x...', evmAddress: '0x...', evmSignature: '0x...', recipientPubkey: wallet.publicKey });
await rc.bridge.getWithdrawals();

Environment Support

EnvironmentRequirements
BrowserAny bundler (Vite, webpack)
Node.js 18+Works out of the box
Node.js < 18Provide node-fetch polyfill
React NativeInstall react-native-get-random-values

TypeScript

Full type declarations are included:

import type { Block, Transaction, Validator, LiquidityPool, NftCollection } from '@rougechain/sdk';

Security

  • All signatures use ML-DSA-65 (FIPS 204), resistant to quantum attacks
  • Private keys never leave your application
  • The SDK does not store keys — persistence is your responsibility

Source

The SDK source code is in the sdk/ directory of the quantum-vault repository.