synor/docs/DEVELOPER_GUIDE.md
Gulshan Yadav 48949ebb3f Initial commit: Synor blockchain monorepo
A complete blockchain implementation featuring:
- synord: Full node with GHOSTDAG consensus
- explorer-web: Modern React blockchain explorer with 3D DAG visualization
- CLI wallet and tools
- Smart contract SDK and example contracts (DEX, NFT, token)
- WASM crypto library for browser/mobile
2026-01-08 05:22:17 +05:30

14 KiB

Synor Developer Guide

Build quantum-secure applications on the Synor blockchain

Table of Contents


Quick Start

Prerequisites

  • Rust 1.75+ (curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh)
  • RocksDB dependencies (see platform-specific instructions below)

macOS:

brew install rocksdb

Ubuntu/Debian:

sudo apt-get install librocksdb-dev libclang-dev

Build from Source

# Clone the repository
git clone https://github.com/g1-technologies/synor.git
cd synor

# Build all components
cargo build --workspace --release

# Run tests
cargo test --workspace

First Steps

# 1. Initialize a new node (creates genesis block for devnet)
./target/release/synord init --network devnet

# 2. Start the node
./target/release/synord run --network devnet

# 3. Create a wallet (in another terminal)
./target/release/synor wallet create

# 4. Check your balance
./target/release/synor balance

Architecture Overview

Synor is a DAG-based blockchain with quantum-resistant cryptography.

┌─────────────────────────────────────────────────────────────────┐
│                         Applications                             │
├──────────────┬──────────────┬──────────────┬───────────────────┤
│   synor-cli  │   Web Wallet │   Explorer   │    Faucet         │
└──────┬───────┴──────┬───────┴──────┬───────┴─────────┬─────────┘
       │              │              │                 │
       └──────────────┴──────────────┴─────────────────┘
                              │
                    ┌─────────▼─────────┐
                    │    synor-rpc      │  JSON-RPC API
                    └─────────┬─────────┘
                              │
       ┌──────────────────────┼──────────────────────┐
       │                      │                      │
┌──────▼──────┐  ┌────────────▼────────────┐  ┌──────▼──────┐
│ synor-network│  │    synord (node)        │  │synor-storage│
│  (libp2p)   │  │  Consensus + Mempool    │  │  (RocksDB)  │
└──────┬──────┘  └────────────┬────────────┘  └──────┬──────┘
       │                      │                      │
       └──────────────────────┼──────────────────────┘
                              │
       ┌──────────────────────┼──────────────────────┐
       │                      │                      │
┌──────▼──────┐  ┌────────────▼────────────┐  ┌──────▼──────┐
│  synor-dag  │  │   synor-consensus       │  │  synor-vm   │
│  (GHOSTDAG) │  │   (UTXO + Validation)   │  │   (WASM)    │
└─────────────┘  └─────────────────────────┘  └─────────────┘
                              │
                    ┌─────────▼─────────┐
                    │   synor-crypto    │
                    │ Ed25519+Dilithium │
                    └───────────────────┘

Key Components

Crate Purpose
synor-crypto Hybrid Ed25519 + Dilithium3 signatures
synor-types Core types (Address, Amount, Transaction, Block)
synor-dag GHOSTDAG consensus ordering
synor-consensus Block/transaction validation, UTXO management
synor-storage RocksDB persistence layer
synor-network P2P networking with libp2p
synor-vm WASM smart contract execution
synor-rpc JSON-RPC API definitions
synord Full node daemon
synor-cli Command-line wallet

Running a Node

Configuration

Create ~/.synor/config.toml:

[network]
network = "testnet"  # mainnet, testnet, or devnet

[p2p]
listen_addr = "/ip4/0.0.0.0/tcp/16111"
max_peers = 50

[rpc]
http_enabled = true
http_addr = "127.0.0.1:16110"
ws_enabled = true
ws_addr = "127.0.0.1:16111"

[mining]
enabled = false
coinbase_address = "synor:qz..."  # Your address for mining rewards
threads = 4

[storage]
data_dir = "~/.synor/data"
cache_size_mb = 512

Network Selection

# Devnet (local development, fast blocks)
synord run --network devnet

# Testnet (public test network)
synord run --network testnet

# Mainnet (production)
synord run --network mainnet

Node Commands

# Initialize chain
synord init --network testnet

# Run node
synord run --network testnet

# Export blocks
synord export --from 0 --to 1000 --output blocks.dat

# Import blocks
synord import --input blocks.dat

Using the CLI Wallet

Wallet Management

# Create new wallet (generates 24-word mnemonic)
synor wallet create

# Recover from mnemonic
synor wallet recover

# Show wallet info
synor wallet info

# List addresses
synor wallet addresses

# Generate new address
synor wallet new-address

Transactions

# Check balance
synor balance

# Send SYNOR
synor send <address> <amount>
# Example: synor send synor:qz1234... 10.5

# View transaction
synor tx <hash>

# View mempool
synor mempool

Block Queries

# Get block by hash
synor block <hash>

# Get block by blue score (DAG height equivalent)
synor block <blue_score>

# Get tips (current DAG tips)
synor tips

# Get chain info
synor info

RPC API Reference

Connect to the RPC server at http://localhost:16110 (HTTP) or ws://localhost:16111 (WebSocket).

Block Methods

// Get block by hash
{
  "jsonrpc": "2.0",
  "method": "synor_getBlock",
  "params": ["<hash>", true],  // hash, include_txs
  "id": 1
}

// Get blocks by blue score
{
  "jsonrpc": "2.0",
  "method": "synor_getBlocksByBlueScore",
  "params": [1000, true],  // blue_score, include_txs
  "id": 1
}

// Get tips
{
  "jsonrpc": "2.0",
  "method": "synor_getTips",
  "params": [],
  "id": 1
}

// Get block count
{
  "jsonrpc": "2.0",
  "method": "synor_getBlockCount",
  "params": [],
  "id": 1
}

Transaction Methods

// Submit transaction
{
  "jsonrpc": "2.0",
  "method": "synor_submitTransaction",
  "params": ["<hex_encoded_tx>"],
  "id": 1
}

// Get mempool size
{
  "jsonrpc": "2.0",
  "method": "synor_getMempoolSize",
  "params": [],
  "id": 1
}

Network Methods

// Get node info
{
  "jsonrpc": "2.0",
  "method": "synor_getInfo",
  "params": [],
  "id": 1
}

// Response:
{
  "version": "0.1.0",
  "protocolVersion": 1,
  "peerCount": 8,
  "blockCount": 12345,
  "blueScore": 12340,
  "mempoolSize": 42,
  "synced": true
}

// Get peer info
{
  "jsonrpc": "2.0",
  "method": "synor_getPeerInfo",
  "params": [],
  "id": 1
}

// Get mining info
{
  "jsonrpc": "2.0",
  "method": "synor_getMiningInfo",
  "params": [],
  "id": 1
}

Contract Methods

// Deploy contract
{
  "jsonrpc": "2.0",
  "method": "synor_deployContract",
  "params": {
    "bytecode": "<hex_wasm>",
    "init_args": "<hex_args>",
    "deployer": "synor:qz...",
    "gas_limit": 1000000
  },
  "id": 1
}

// Call contract
{
  "jsonrpc": "2.0",
  "method": "synor_callContract",
  "params": {
    "contract_id": "<hex_id>",
    "method": "transfer",
    "args": "<hex_args>",
    "caller": "synor:qz...",
    "value": 0,
    "gas_limit": 100000
  },
  "id": 1
}

Smart Contract Development

Quick Start

# Create new contract project
./scripts/new-contract.sh my_token

# Build contract
cd contracts/my_token
cargo build --target wasm32-unknown-unknown --release

# Optimize WASM (reduces size significantly)
synor-compiler optimize target/wasm32-unknown-unknown/release/my_token.wasm

Contract Template

// contracts/my_token/src/lib.rs
#![no_std]

use synor_sdk::prelude::*;

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

    // Storage keys
    const TOTAL_SUPPLY: &[u8] = b"total_supply";
    const BALANCES: &[u8] = b"balances";

    /// Initialize the token
    #[init]
    pub fn init(initial_supply: u64) {
        let caller = env::caller();
        storage::set(TOTAL_SUPPLY, &initial_supply.to_le_bytes());
        storage::set(&balance_key(&caller), &initial_supply.to_le_bytes());

        env::emit_event("Initialized", &[
            ("supply", &initial_supply.to_string()),
            ("owner", &hex::encode(&caller)),
        ]);
    }

    /// Get balance of an address
    #[view]
    pub fn balance_of(address: Address) -> u64 {
        storage::get(&balance_key(&address))
            .map(|b| u64::from_le_bytes(b.try_into().unwrap()))
            .unwrap_or(0)
    }

    /// Transfer tokens
    #[call]
    pub fn transfer(to: Address, amount: u64) -> bool {
        let caller = env::caller();
        let from_balance = balance_of(caller);

        if from_balance < amount {
            return false;
        }

        let to_balance = balance_of(to);

        storage::set(&balance_key(&caller), &(from_balance - amount).to_le_bytes());
        storage::set(&balance_key(&to), &(to_balance + amount).to_le_bytes());

        env::emit_event("Transfer", &[
            ("from", &hex::encode(&caller)),
            ("to", &hex::encode(&to)),
            ("amount", &amount.to_string()),
        ]);

        true
    }

    fn balance_key(address: &Address) -> Vec<u8> {
        [BALANCES, address.as_bytes()].concat()
    }
}

Host Functions

Contracts can call these host functions (see contracts/HOST_FUNCTIONS.md for details):

Function Description
env::caller() Get caller address
env::block_height() Current block height
env::timestamp() Block timestamp
env::value() SYNOR sent with call
storage::get(key) Read from storage
storage::set(key, value) Write to storage
storage::delete(key) Delete from storage
env::emit_event(name, data) Emit event
crypto::hash(data) Blake3 hash
crypto::verify(pubkey, msg, sig) Verify signature

Testing Contracts

#[cfg(test)]
mod tests {
    use synor_contract_test::*;

    #[test]
    fn test_transfer() {
        let mut env = TestEnv::new();
        let alice = env.create_account(1000);
        let bob = env.create_account(0);

        // Deploy contract
        let contract = env.deploy("my_token", &alice, &[1000u64.to_le_bytes()]);

        // Transfer tokens
        env.call(&contract, &alice, "transfer", &[bob.as_bytes(), &100u64.to_le_bytes()]);

        // Check balances
        assert_eq!(env.view(&contract, "balance_of", &alice.as_bytes()), 900u64);
        assert_eq!(env.view(&contract, "balance_of", &bob.as_bytes()), 100u64);
    }
}

SDK Integration

JavaScript/TypeScript

import { SynorClient, Wallet } from '@synor/sdk';

// Connect to node
const client = new SynorClient('http://localhost:16110');

// Create wallet from mnemonic
const wallet = Wallet.fromMnemonic(
  'abandon abandon abandon ... art',
  '' // passphrase
);

console.log('Address:', wallet.address);

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

// Send transaction
const tx = await wallet.createTransaction({
  to: 'synor:qz1234...',
  amount: '10.5',
});
const result = await client.submitTransaction(tx);
console.log('TX Hash:', result.transactionId);

Rust

use synor_types::{Address, Amount};
use synor_crypto::{Mnemonic, HybridKeypair, Network};

// Generate new wallet
let mnemonic = Mnemonic::generate(24)?;
let keypair = HybridKeypair::from_mnemonic(&mnemonic, "")?;
let address = keypair.address(Network::Testnet);

println!("Mnemonic: {}", mnemonic.phrase());
println!("Address: {}", address);

// Sign a message
let message = b"Hello, Synor!";
let signature = keypair.sign(message);

// Verify
assert!(keypair.public_key().verify(message, &signature).is_ok());

Troubleshooting

Common Issues

"Failed to open database"

# Check data directory permissions
ls -la ~/.synor/data

# Remove corrupted database (WARNING: loses local data)
rm -rf ~/.synor/data
synord init --network testnet

"No peers found"

# Check network connectivity
synor peers

# Manually add peer
synor peer add /ip4/1.2.3.4/tcp/16111/p2p/<peer_id>

"Transaction rejected"

  • Check sufficient balance (including fees)
  • Verify recipient address format
  • Check mempool isn't full

Logs

# Enable debug logging
RUST_LOG=debug synord run

# Specific component logging
RUST_LOG=synor_network=debug,synor_consensus=info synord run

Resources


Last updated: January 7, 2026