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
14 KiB
14 KiB
Synor Developer Guide
Build quantum-secure applications on the Synor blockchain
Table of Contents
- Quick Start
- Architecture Overview
- Running a Node
- Using the CLI Wallet
- RPC API Reference
- Smart Contract Development
- SDK Integration
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
- GitHub: https://github.com/g1-technologies/synor
- Testnet Faucet: https://faucet.synor.cc
- Block Explorer: https://explorer.synor.cc
- Discord: https://discord.gg/synor
Last updated: January 7, 2026