Skip to content

Developer Guide

Overview

This guide provides comprehensive instructions for developers who want to build, deploy, integrate with, or contribute to the Moby Market whale trading infrastructure.

Development Environment Setup

Prerequisites

# Required tools
node >= 18.0.0
npm >= 8.0.0
rustc >= 1.70.0
solana-cli >= 1.16.0
anchor-cli >= 0.28.0

# Optional but recommended
docker >= 20.10.0
git >= 2.30.0

Installation

1. Clone the Repository

git clone https://github.com/moby-market/moby-market.git
cd moby-market

2. Install Dependencies

# Install Node.js dependencies
npm install

# Install Rust dependencies
cd programs && cargo build
cd ..

# Install Anchor dependencies
anchor build

3. Environment Configuration

# Copy environment template
cp .env.example .env

# Configure your environment variables
SOLANA_NETWORK=devnet
ANCHOR_PROVIDER_URL=https://api.devnet.solana.com
ANCHOR_WALLET=~/.config/solana/id.json
PYTHNET_RPC=https://pythnet.rpc.pythnet.pyth.network

Project Structure

moby-market/
├── programs/                   # Solana programs (smart contracts)
│   ├── otc-settlement/        # OTC trading program
│   ├── execution-engine/      # TWAP/VWAP algorithms
│   ├── privacy-layer/         # ZK proof system
│   └── oracle-aggregator/     # Price feed aggregation
├── app/                       # Frontend application
│   ├── components/            # React components
│   ├── hooks/                 # Custom React hooks
│   ├── utils/                 # Utility functions
│   └── types/                 # TypeScript definitions
├── sdk/                       # Client SDK
│   ├── typescript/            # TypeScript SDK
│   ├── python/                # Python SDK
│   └── rust/                  # Rust SDK
├── tests/                     # Test suites
│   ├── integration/           # Integration tests
│   ├── unit/                  # Unit tests
│   └── e2e/                   # End-to-end tests
├── docs/                      # Documentation
├── scripts/                   # Deployment and utility scripts
└── circuits/                  # ZK circuits
    ├── transaction/           # Transaction privacy circuits
    ├── range-proof/           # Range proof circuits
    └── compliance/            # Compliance circuits

Building from Source

Smart Contracts

# Build all programs
anchor build

# Build specific program
cd programs/otc-settlement
cargo build-bpf

# Run program tests
anchor test

Frontend Application

# Development build
npm run dev

# Production build
npm run build

# Run tests
npm test

# Type checking
npm run type-check

SDK

# Build TypeScript SDK
cd sdk/typescript
npm run build

# Build Python SDK
cd sdk/python
pip install -e .
python -m build

# Build Rust SDK
cd sdk/rust
cargo build

ZK Circuits

# Install circuit dependencies
cd circuits
npm install

# Compile circuits
npm run compile

# Generate proving and verification keys
npm run setup

# Run circuit tests
npm test

Testing

Smart Contract Tests

# Run all program tests
anchor test

# Test specific program
anchor test --program otc-settlement

# Run with coverage
anchor test --coverage

Integration Tests

# Set up test environment
npm run test:setup

# Run integration tests
npm run test:integration

# Run specific test suite
npm run test:integration -- --grep "OTC Trading"

Circuit Tests

# Test circuit compilation
cd circuits
npm run test:compile

# Test proof generation
npm run test:prove

# Test proof verification
npm run test:verify

Deployment

Local Development Network

# Start local validator
solana-test-validator

# Deploy programs to local network
anchor deploy --provider.cluster localnet

# Initialize program states
npm run initialize:local

Devnet Deployment

# Configure for devnet
solana config set --url devnet

# Fund deployment wallet
solana airdrop 10

# Deploy to devnet
anchor deploy --provider.cluster devnet

# Verify deployment
solana program show <program_id>

Mainnet Deployment

# Configure for mainnet
solana config set --url mainnet-beta

# Deploy with multisig (recommended)
anchor deploy --provider.cluster mainnet-beta --program-id <program_id>

# Initialize with governance
npm run initialize:mainnet

SDK Usage

TypeScript SDK

import { MobyMarketSDK } from '@moby-market/sdk';

// Initialize SDK
const sdk = new MobyMarketSDK({
  network: 'devnet',
  wallet: walletAdapter,
});

// Create OTC order
const order = await sdk.otc.createOrder({
  tokenSell: 'SOL',
  tokenBuy: 'USDC',
  amountSell: 1000,
  amountBuy: 150000,
  expiry: Date.now() + 86400000, // 24 hours
});

// Submit TWAP order
const twapOrder = await sdk.execution.submitTWAP({
  tokenIn: 'SOL',
  tokenOut: 'USDC',
  totalAmount: 10000,
  timeWindow: 3600, // 1 hour
  numSplits: 12,    // Every 5 minutes
});

// Use privacy features
const privateTransfer = await sdk.privacy.createConfidentialTransfer({
  amount: 5000,
  recipient: recipientPublicKey,
  asset: 'SOL',
});

Python SDK

from moby_market import MobyMarketClient

# Initialize client
client = MobyMarketClient(
    network='devnet',
    private_key_path='path/to/keypair.json'
)

# Create OTC order
order = client.otc.create_order(
    token_sell='SOL',
    token_buy='USDC',
    amount_sell=1000,
    amount_buy=150000,
    expiry=int(time.time()) + 86400
)

# Submit VWAP order
vwap_order = client.execution.submit_vwap(
    token_pair=('SOL', 'USDC'),
    total_amount=5000,
    target_volume_participation=500  # 5%
)

# Generate ZK proof
proof = client.privacy.generate_proof(
    circuit_type='transaction',
    public_inputs=[...],
    private_witnesses=[...]
)

Rust SDK

use moby_market_sdk::{MobyMarketClient, NetworkConfig};

// Initialize client
let client = MobyMarketClient::new(NetworkConfig {
    cluster: Cluster::Devnet,
    commitment: CommitmentConfig::confirmed(),
});

// Create OTC order
let order = client.otc().create_order(OTCOrderParams {
    token_sell: sol_mint,
    token_buy: usdc_mint,
    amount_sell: 1000 * LAMPORTS_PER_SOL,
    amount_buy: 150_000 * 1_000_000, // 150k USDC
    expiry: SystemTime::now()
        .duration_since(UNIX_EPOCH)?
        .as_secs() as i64 + 86400,
    ..Default::default()
}).await?;

// Submit intent-based order
let intent = client.execution().submit_intent(TradingIntent {
    intent_type: IntentType::BestExecution {
        token_in: sol_mint,
        token_out: usdc_mint,
        amount: 10000 * LAMPORTS_PER_SOL,
        min_output: 1_400_000 * 1_000_000, // Min 1.4M USDC
    },
    constraints: vec![
        Constraint::MaxSlippage(50), // 0.5%
        Constraint::PreferredVenues(vec![raydium_program, orca_program]),
    ],
    ..Default::default()
}).await?;

Program Development

Creating a New Program

# Generate new program
anchor new my-program --template basic

# Program structure
programs/my-program/
├── Cargo.toml
├── Xargo.toml
└── src/
    ├── lib.rs        # Program entry point
    ├── instructions/ # Instruction handlers
    ├── state/        # Account structures
    └── errors.rs     # Custom error types

Program Template

use anchor_lang::prelude::*;

declare_id!("YourProgramIdHere");

#[program]
pub mod my_program {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let state = &mut ctx.accounts.state;
        state.authority = ctx.accounts.authority.key();
        state.initialized = true;
        Ok(())
    }

    pub fn execute_operation(
        ctx: Context<ExecuteOperation>,
        amount: u64,
    ) -> Result<()> {
        // Validate inputs
        require!(amount > 0, ErrorCode::InvalidAmount);

        // Perform operation
        let state = &mut ctx.accounts.state;
        state.total_amount = state.total_amount
            .checked_add(amount)
            .ok_or(ErrorCode::MathOverflow)?;

        emit!(OperationExecuted {
            amount,
            total: state.total_amount,
            timestamp: Clock::get()?.unix_timestamp,
        });

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(
        init,
        payer = authority,
        space = 8 + State::INIT_SPACE,
        seeds = [b"state"],
        bump
    )]
    pub state: Account<'info, State>,
    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct ExecuteOperation<'info> {
    #[account(
        mut,
        seeds = [b"state"],
        bump,
        has_one = authority
    )]
    pub state: Account<'info, State>,
    pub authority: Signer<'info>,
}

#[account]
#[derive(InitSpace)]
pub struct State {
    pub authority: Pubkey,
    pub initialized: bool,
    pub total_amount: u64,
}

#[event]
pub struct OperationExecuted {
    pub amount: u64,
    pub total: u64,
    pub timestamp: i64,
}

#[error_code]
pub enum ErrorCode {
    #[msg("Invalid amount provided")]
    InvalidAmount,
    #[msg("Mathematical overflow")]
    MathOverflow,
}

ZK Circuit Development

Circuit Template

// circuits/my-circuit/circuit.ts
import { Field, SmartContract, state, State, method, Poseidon } from 'snarkyjs';

export class MyCircuit extends SmartContract {
  @state(Field) commitment = State<Field>();

  @method
  proveKnowledge(
    secret: Field,
    publicValue: Field
  ) {
    // Verify that hash(secret) = commitment
    const hash = Poseidon.hash([secret]);
    const currentCommitment = this.commitment.get();
    this.commitment.assertEquals(currentCommitment);
    hash.assertEquals(currentCommitment);

    // Verify that secret satisfies some constraint
    secret.assertLte(publicValue);
  }

  @method
  updateCommitment(newCommitment: Field) {
    this.commitment.set(newCommitment);
  }
}

Circuit Testing

// circuits/my-circuit/test.ts
import { MyCircuit } from './circuit';
import { Field, Mina, PrivateKey, PublicKey } from 'snarkyjs';

describe('MyCircuit', () => {
  let deployerAccount: PublicKey,
      deployerKey: PrivateKey,
      zkAppAddress: PublicKey,
      zkAppPrivateKey: PrivateKey,
      zkApp: MyCircuit;

  beforeAll(async () => {
    await MyCircuit.compile();
  });

  beforeEach(() => {
    const Local = Mina.LocalBlockchain({ proofsEnabled: false });
    Mina.setActiveInstance(Local);

    ({ privateKey: deployerKey, publicKey: deployerAccount } =
      Local.testAccounts[0]);

    zkAppPrivateKey = PrivateKey.random();
    zkAppAddress = zkAppPrivateKey.toPublicKey();
    zkApp = new MyCircuit(zkAppAddress);
  });

  it('should prove knowledge correctly', async () => {
    const secret = Field(12345);
    const commitment = Poseidon.hash([secret]);

    // Deploy contract
    const txn = await Mina.transaction(deployerAccount, () => {
      zkApp.deploy();
      zkApp.updateCommitment(commitment);
    });
    await txn.prove();
    await txn.sign([deployerKey, zkAppPrivateKey]).send();

    // Prove knowledge
    const txn2 = await Mina.transaction(deployerAccount, () => {
      zkApp.proveKnowledge(secret, Field(20000));
    });
    await txn2.prove();
    await txn2.sign([deployerKey]).send();
  });
});

Integration Patterns

Cross-Program Invocations

// Calling another program from your program
use anchor_lang::prelude::*;

#[derive(Accounts)]
pub struct CrossProgramCall<'info> {
    pub authority: Signer<'info>,

    /// CHECK: This account is passed to the target program
    pub target_account: UncheckedAccount<'info>,

    pub target_program: Program<'info, TargetProgram>,
}

pub fn call_external_program(
    ctx: Context<CrossProgramCall>,
    data: Vec<u8>,
) -> Result<()> {
    let cpi_context = CpiContext::new(
        ctx.accounts.target_program.to_account_info(),
        target_program::cpi::accounts::ExecuteInstruction {
            authority: ctx.accounts.authority.to_account_info(),
            target_account: ctx.accounts.target_account.to_account_info(),
        }
    );

    target_program::cpi::execute_instruction(cpi_context, data)?;
    Ok(())
}

Oracle Integration

use pyth_sdk_solana::{load_price_feed_from_account_info, PriceFeed};

pub fn get_price_from_oracle(
    price_account: &AccountInfo,
) -> Result<i64> {
    let price_feed = load_price_feed_from_account_info(price_account)?;
    let current_price = price_feed.get_price_unchecked();

    // Check if price is fresh (within last 60 seconds)
    let current_time = Clock::get()?.unix_timestamp;
    require!(
        current_time - current_price.publish_time < 60,
        ErrorCode::StalePriceFeed
    );

    Ok(current_price.price)
}

Performance Optimization

Compute Unit Optimization

use anchor_lang::prelude::*;

// Set compute unit limit and price
#[derive(Accounts)]
pub struct OptimizedInstruction<'info> {
    /// CHECK: Compute budget program
    #[account(executable)]
    pub compute_budget_program: UncheckedAccount<'info>,
}

pub fn optimized_operation(
    ctx: Context<OptimizedInstruction>,
) -> Result<()> {
    // Set compute unit limit
    let set_limit_ix = solana_program::compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(200_000);

    solana_program::program::invoke(
        &set_limit_ix,
        &[ctx.accounts.compute_budget_program.to_account_info()],
    )?;

    // Set compute unit price
    let set_price_ix = solana_program::compute_budget::ComputeBudgetInstruction::set_compute_unit_price(1000);

    solana_program::program::invoke(
        &set_price_ix,
        &[ctx.accounts.compute_budget_program.to_account_info()],
    )?;

    // Perform optimized operations
    perform_efficient_calculations()?;

    Ok(())
}

Account Optimization

// Use zero-copy deserialization for large accounts
#[account(zero_copy)]
pub struct LargeAccount {
    pub data: [u8; 10000],
    pub metadata: AccountMetadata,
}

// Implement custom serialization for optimal space usage
impl LargeAccount {
    pub const INIT_SPACE: usize = 8 + // discriminator
        10000 +                      // data array
        32 +                         // metadata.authority
        8 +                          // metadata.created_at
        1;                          // metadata.active (bool)
}

Monitoring and Debugging

Event Logging

// Define comprehensive events for monitoring
#[event]
pub struct OrderCreated {
    pub order_id: [u8; 32],
    pub trader: Pubkey,
    pub token_in: Pubkey,
    pub token_out: Pubkey,
    pub amount_in: u64,
    pub min_amount_out: u64,
    pub order_type: u8,
    pub timestamp: i64,
}

#[event]
pub struct OrderExecuted {
    pub order_id: [u8; 32],
    pub executed_amount: u64,
    pub execution_price: u64,
    pub venue: Pubkey,
    pub gas_used: u64,
    pub timestamp: i64,
}

// Emit events for monitoring
pub fn create_order(ctx: Context<CreateOrder>, params: OrderParams) -> Result<()> {
    let order = &mut ctx.accounts.order;

    // ... order creation logic ...

    emit!(OrderCreated {
        order_id: order.id,
        trader: order.trader,
        token_in: order.token_in,
        token_out: order.token_out,
        amount_in: order.amount_in,
        min_amount_out: order.min_amount_out,
        order_type: order.order_type as u8,
        timestamp: Clock::get()?.unix_timestamp,
    });

    Ok(())
}

Error Handling

#[error_code]
pub enum ProgramError {
    #[msg("Insufficient balance for operation")]
    InsufficientBalance,

    #[msg("Order has expired")]
    OrderExpired,

    #[msg("Slippage tolerance exceeded")]
    ExcessiveSlippage,

    #[msg("Oracle price is stale")]
    StalePriceFeed,

    #[msg("Unauthorized operation")]
    Unauthorized,

    #[msg("Mathematical overflow detected")]
    MathOverflow,

    #[msg("Invalid account provided")]
    InvalidAccount,
}

// Use Result types consistently
pub fn safe_operation(amount: u64) -> Result<u64> {
    if amount == 0 {
        return Err(ProgramError::InsufficientBalance.into());
    }

    amount.checked_mul(2)
        .ok_or(ProgramError::MathOverflow.into())
}

Contributing

Code Style

# Format Rust code
cargo fmt

# Format TypeScript code
npm run format

# Run linters
cargo clippy
npm run lint

Commit Guidelines

# Commit message format
type(scope): description

# Examples
feat(otc): add dark pool order support
fix(privacy): resolve nullifier collision issue
docs(api): update TWAP endpoint documentation
test(circuits): add range proof test cases

Pull Request Process

  1. Fork and Branch

    git checkout -b feature/your-feature-name
    

  2. Make Changes

  3. Follow code style guidelines
  4. Add comprehensive tests
  5. Update documentation

  6. Test Thoroughly

    # Run all tests
    npm run test:all
    
    # Check coverage
    npm run coverage
    

  7. Submit PR

  8. Clear description of changes
  9. Link to related issues
  10. Include test results

Development Workflow

graph TD
    A[Fork Repository] --> B[Create Feature Branch]
    B --> C[Implement Changes]
    C --> D[Write Tests]
    D --> E[Update Documentation]
    E --> F[Run Test Suite]
    F --> G{Tests Pass?}
    G -->|No| C
    G -->|Yes| H[Submit PR]
    H --> I[Code Review]
    I --> J{Approved?}
    J -->|No| C
    J -->|Yes| K[Merge to Main]

Resources

Documentation

Tools and Libraries

Community

Troubleshooting

Common Issues

Program Deploy Errors

# Insufficient SOL for deployment
solana airdrop 5

# Program account already exists
solana program close <program-id>
anchor deploy --program-id <new-program-id>

Test Failures

# Clear test ledger
rm -rf test-ledger/

# Rebuild programs
anchor clean && anchor build

# Run specific test
anchor test --skip-build -- --grep "test name"

Circuit Compilation Issues

# Clear circuit cache
cd circuits && npm run clean

# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install

# Recompile circuits
npm run compile

Getting Help

  1. Check existing GitHub Issues
  2. Ask questions in Discord
  3. Create detailed bug reports with:
  4. Environment details
  5. Steps to reproduce
  6. Expected vs actual behavior
  7. Relevant logs/error messages