Architecture Overview

Nester follows a layered architecture separating concerns across clients, backend services, and the blockchain.

System Diagram

┌─────────────────────────────────────────────────────────────┐
│                         CLIENTS                             │
│                                                             │
│   Website (Next.js)    DApp (Next.js 16)    Mobile (RN)    │
│   Marketing/Landing    Stellar Wallets      iOS/Android    │
│                              │              (future)       │
└──────────────────────────────┼──────────────────────────────┘
                               │ REST API
┌──────────────────────────────┼──────────────────────────────┐
│                       BACKEND LAYER                         │
│                              │                              │
│  ┌───────────────────────────▼───────────────────────────┐  │
│  │           API Gateway (Go + Chi Router)                │  │
│  │                                                       │  │
│  │  ┌─────────────┐ ┌──────────────┐ ┌───────────────┐  │  │
│  │  │ Vault       │ │ Portfolio    │ │ User / Auth   │  │  │
│  │  │ Manager     │ │ Service      │ │ Service       │  │  │
│  │  └─────────────┘ └──────────────┘ └───────────────┘  │  │
│  │  ┌─────────────┐ ┌──────────────┐ ┌───────────────┐  │  │
│  │  │ Yield       │ │ Auto-Invest  │ │ Event         │  │  │
│  │  │ Router      │ │ Scheduler    │ │ Listener      │  │  │
│  │  └─────────────┘ └──────────────┘ └───────────────┘  │  │
│  │  ┌─────────────┐                                     │  │
│  │  │ Rebalancer  │                                     │  │
│  │  │ Service     │                                     │  │
│  │  └─────────────┘                                     │  │
│  └───────────────────────────────────────────────────────┘  │
│                              │                              │
│  ┌───────────────────────────▼───────────────────────────┐  │
│  │              PostgreSQL (Supabase)                     │  │
│  │  users │ vaults │ positions │ shares │ yield_snapshots │  │
│  │  transactions │ events │ auto_invest_mandates          │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                               │
┌──────────────────────────────┼──────────────────────────────┐
│              BLOCKCHAIN LAYER (Stellar / Soroban)           │
│                              │                              │
│  ┌───────────────────────────▼───────────────────────────┐  │
│  │  Smart Contracts (Rust / Soroban SDK)                  │  │
│  │                                                       │  │
│  │  VaultFactory          Vault Contracts                 │  │
│  │  Deploy/manage         deposit / withdraw / position   │  │
│  │  vault instances       nVault share token mint/burn    │  │
│  │                        maturity & penalty logic        │  │
│  │  Auto-Invest Mandates  Yield Source Adapters           │  │
│  │  recurring deposit     Blend / Kamino / Aave           │  │
│  │  authorization         deposit / withdraw / balanceOf  │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                             │
│  Stellar Network: Horizon API / Soroban RPC                 │
└─────────────────────────────────────────────────────────────┘

Data Flow: Deposit

User clicks "Deposit 1000 USDC into Balanced Vault"
    │
    ▼
┌─────────────────┐     ┌──────────────────┐
│ Frontend         │────▶│ Go Backend       │
│ Build Soroban TX │     │ POST /deposit    │
└────────┬────────┘     │ Validate + build │
         │              │ TX envelope      │
         ▼              └────────┬─────────┘
┌─────────────────┐              │
│ Wallet Extension │◀────────────┘
│ Sign TX          │     TX envelope returned
└────────┬────────┘
         │ Signed TX
         ▼
┌─────────────────┐     ┌──────────────────┐
│ Stellar Network  │────▶│ Event Listener   │
│ Execute TX       │     │ Index deposit    │
│ Vault.deposit()  │     │ Update positions │
└─────────────────┘     └──────────────────┘

Data Flow: Auto-Invest

User authorizes "Deposit 200 USDC into Balanced Vault weekly"
    │
    ▼
┌──────────────┐    ┌────────────────┐    ┌─────────────┐
│ Frontend     │───▶│ Go Backend     │───▶│ Scheduler   │
│ POST         │    │ Validate +     │    │ Registers   │
│ /mandates    │    │ store mandate  │    │ next run    │
└──────────────┘    └───────┬────────┘    └──────┬──────┘
                            │                     │ every cycle
                            ▼                     ▼
                   ┌────────────────┐    ┌─────────────┐
                   │ Soroban        │───▶│ Vault       │
                   │ Mandate        │    │ deposit()   │
                   │ authorization  │    │ shares mint │
                   └────────────────┘    └──────┬──────┘
                                                │
                   ┌────────────────┐           │
                   │ Event Listener │◀──────────┘
                   │ Index deposit  │
                   │ Update position│
                   └────────────────┘

Project Structure

bash
nester/
├── apps/
│   ├── website/              # Marketing site (Next.js + pnpm)
│   ├── dapp/
│   │   ├── frontend/         # DApp (Next.js 16 + npm)
│   │   └── contracts/        # Soroban smart contracts (Rust)
│   └── api/                  # API Gateway (Go + Chi + PostgreSQL)
├── packages/
│   └── contracts/            # Shared contract types/ABIs
└── mobile/                   # React Native app (future)

Database Schema

sql
-- Core tables (PostgreSQL / Supabase)
CREATE TABLE users (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    wallet_addr  TEXT UNIQUE NOT NULL,
    created_at   TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE vaults (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name         TEXT NOT NULL,         -- "Conservative", "Balanced", etc.
    vault_type   TEXT NOT NULL,         -- conservative | balanced | growth
    contract_id  TEXT NOT NULL,         -- Soroban contract address
    total_shares NUMERIC DEFAULT 0,
    total_assets NUMERIC DEFAULT 0,
    apy_current  NUMERIC DEFAULT 0,
    status       TEXT DEFAULT 'active', -- active | paused
    created_at   TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE positions (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id      UUID REFERENCES users(id),
    vault_id     UUID REFERENCES vaults(id),
    shares       NUMERIC NOT NULL,
    deposited_at TIMESTAMPTZ DEFAULT now(),
    maturity_at  TIMESTAMPTZ,
    UNIQUE(user_id, vault_id)
);

CREATE TABLE yield_snapshots (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    vault_id     UUID REFERENCES vaults(id),
    apy          NUMERIC NOT NULL,
    tvl          NUMERIC NOT NULL,
    recorded_at  TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE auto_invest_mandates (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id      UUID REFERENCES users(id),
    vault_id     UUID REFERENCES vaults(id),
    amount_usd   NUMERIC NOT NULL,
    cadence      TEXT NOT NULL,          -- daily | weekly | monthly
    status       TEXT DEFAULT 'active',  -- active | paused | cancelled
    next_run_at  TIMESTAMPTZ NOT NULL,
    created_at   TIMESTAMPTZ DEFAULT now()
);