Smart contracts, servers & all the techy pirate stuff!
SEAS OF SOLANA
Technical Architecture Document
Version 2.0
July 2026
1. Executive Summary
This document describes the implemented technical architecture of Seas Of Solana, a blockchain-based gaming ecosystem built on Solana. The platform leverages the original NFT collections (Crypto Coves, Crypto Captains, and Sea Rovers) to create an interconnected economy where players explore, battle, and build their pirate empires.
The stack is deliberately lean: a static React frontend, a single server-authoritative API service, one PostgreSQL database, and one Anchor program powering the $DOUBLOON token. Asset ownership and token settlement live on-chain; all gameplay is simulated and validated on the server for speed, cost, and fairness.
2. System Overview
2.1 High-Level Architecture
The system follows a hybrid architecture combining on-chain asset ownership and token settlement with off-chain, server-authoritative game logic.
| Layer | Components | Purpose |
| Presentation | React 19 + Vite SPA (play.html), Solana wallet-adapter |
UI, wallet connection, battle replay viewer; hosted on GitHub Pages |
| API | Hono (Node/TypeScript) on Fly.io | REST endpoints, SIWS authentication, rate limiting, CORS |
| Game Logic | Voyage resolver, deterministic combat engine, job/ability catalogs | Server-authoritative gameplay: every cost and reward computed server-side |
| Blockchain | Anchor $DOUBLOON program, Metaplex NFT metadata (Solana devnet) | Asset ownership, token mint/burn settlement |
| Data | PostgreSQL (Fly Postgres) via Drizzle ORM | Game state, settlement ledger, auth nonces, rate-limit counters |
2.2 Core Design Principles
Server-Authoritative: The client never computes outcomes; every cost, reward, and battle result is calculated and validated on the server
Hybrid On-Chain/Off-Chain: NFT ownership and $DOUBLOON balances on Solana; game state off-chain for performance
One-Time Delegation: Players sign a single token approval at onboarding; afterwards the backend executes all mints and burns and pays all fees — players never need SOL
Exactly-Once Settlement: A database ledger guarantees no reward is minted twice and no spend is burned twice, even under concurrency or retries
Deterministic Simulation: Battles are seeded so any fight can be reproduced and replayed exactly
Dev-Mode Parity: Without chain configuration the identical flows settle in the database, so local development needs no blockchain
3. Blockchain Layer
3.1 The $DOUBLOON Anchor Program
A single smart contract, written with the Anchor framework, manages the $DOUBLOON SPL token (9 decimals) on Solana devnet.
| Instruction | Responsibilities |
| initialize | Creates the Config PDA, records the admin key, establishes the authority PDA as mint and freeze authority |
| mint_doubloons | Admin-gated mint of reward tokens directly to a player's token account |
| spend_doubloons | Admin-gated burn from a player's token account via the delegated authority PDA |
| set_admin | Rotates the admin key stored in the Config PDA |
The program uses two Program Derived Addresses: a Config PDA that stores the admin key, and an authority PDA that serves as both the token's mint/freeze authority and the player-approved delegate.
3.2 One-Time Delegate Approval
At onboarding, each player signs a single approve transaction delegating the authority PDA over their $DOUBLOON account. From then on the backend mints rewards and burns spends with no per-action player signatures — the backend pays all transaction fees, so players never need SOL to play.
3.3 Exactly-Once Settlement
Every mint and burn is recorded in a token_ledger table before it touches the chain. An atomic claim on each ledger row means concurrent requests cannot double-mint, and failed transactions retry safely without duplicating rewards. In dev mode (no chain configured), the identical flows settle balances in the database, so the full game runs locally with no blockchain.
3.4 NFT Metadata & Trait Mapping
The original collections follow the Metaplex Token Metadata Standard. The backend fetches each NFT's metadata, verifies it by collection and update authority (names alone are not trusted), and maps raw traits through tier tables into in-game stats. Raw attributes are always preserved, re-syncs never wipe player progression, and the real NFT artwork renders in-game.
Sea Rovers (9 traits): Hull material determines ship class (Sloop, Brigantine, Ironclad, Interceptor, Ghost Ship, Crystal Ship, Sol Galleon); sails map to speed, crew paint to berths and cannons, bow accessories to cargo or cannons, and remaining traits to hull strength and rarity
Crypto Captains (4 traits): 16 archetypes with distinct stat spreads, from Pirate up to legendary Poseidon, Skeleton King, Blackbeard, and The Child; eyes map to luck, floor to morale, background to navigation
Crypto Coves (5 traits): Resource buildings drive production (Lumber Mill → Timber, Stone Mine → Iron, Shipyard → both, Tavern → Rum, treasure accessories → Gold); defenses map to levels 1–5 and overall rarity sets the island class (Atoll through Citadel) with 2–10 building slots
4. Backend Architecture
4.1 API Service
The backend is a single Node/TypeScript service built on the Hono web framework with Drizzle ORM over PostgreSQL. It is containerized with Docker and deployed to Fly.io; database migrations run automatically at release time. All game logic is server-authoritative — the client submits intents, the server computes outcomes.
| Module | Responsibilities |
| Auth | SIWS challenge/verify flow, JWT issuance, nonce lifecycle |
| NFT Sync | Metadata fetch, collection verification, trait-to-stat mapping for ships, captains, and coves |
| Voyages | Voyage start/claim, resource cost validation, success calculation, reward settlement |
| Combat | Deterministic battle simulation, arena tiers, raid boarding battles, battle log storage |
| Jobs & Abilities | Job unlocks and prerequisites, JP spending, ability purchases, stat multipliers |
| Token | $DOUBLOON mint/burn orchestration through the exactly-once ledger |
4.2 Combat Engine
Battles are simulated entirely on the server as deterministic, seeded ATB (active-time battle) fights — the same seed always reproduces the same battle. The engine supports statuses (Poison, Stun, Attack Up, Protect, Haste, Slow, Regen), cooldowns, luck-based critical hits, counter-attacks, lifesteal, and survive-lethal effects. The full battle log is stored in the database and streamed to the client, which acts purely as a replay player — animated HP bars, floating damage numbers, and speed controls — with battle history re-watchable at any time.
Content is code, not data entry: the job catalog (10 jobs, 40 abilities), arena tiers (5 PvE tiers from Wharf Rats to Ghost Fleet), and ability behaviors are defined as versioned server-side catalogs, so balance changes ship with a deploy and can never drift from the simulation.
4.3 Database Schema
Primary Database (PostgreSQL)
A single relational database, managed through Drizzle ORM migrations, holds all game state:
profiles: wallet-keyed player accounts, resources, and progression
ships: synced Sea Rover NFTs with mapped class, speed, cargo, cannons, and durability
captains: synced Crypto Captain NFTs with stats, XP, job levels, and learned abilities
coves: synced Crypto Cove NFTs with production rates, defense levels, and building slots
voyage_definitions / active_voyages / voyage_crew: voyage types, in-flight voyages, and crew assignments
battles: seed, participants, full battle log, and rewards for every simulated fight
token_ledger: exactly-once mint/burn settlement records with atomic claiming
siws_nonces: single-use authentication nonces with 5-minute expiry
rate_limits: fixed-window rate-limiting counters per wallet and action
(A legacy job_classes table exists but is superseded by the server-side job catalog.)
5. Frontend Architecture
5.1 Technology Stack
| Concern | Technology | Notes |
| Web Application | React 19 + Vite | Single-page app served from play.html; @solana/web3.js, @solana/wallet-adapter (Phantom, Solflare) |
| Hosting | GitHub Pages | Static build output; no server-side rendering required |
| Battle Viewer | React replay player | Renders the server's battle log: animated HP bars, floating damage/crit numbers, 1×/2×/skip speed controls |
5.2 State Management
The frontend is a thin, trusted-display layer over the API:
Wallet State: Managed by the wallet-adapter context; connection status, public key, message signing for SIWS
Server State: Fetched from the REST API with the session JWT; the server is the single source of truth for resources, crews, voyages, and battles
UI State: Component-local React state for panels, modals, and replay animations
5.3 Client/Server Contract
The client never computes gameplay outcomes. It submits intents (start a voyage, enter the arena, buy an ability) and renders what the server returns:
Voyage timers and claimable results
Complete battle logs, replayed locally at the player's chosen speed
Cove production and resource balances
Job trees, JP balances, and ability unlocks
Real NFT artwork rendered in-game for ships, captains, and coves
6. Infrastructure & DevOps
6.1 Deployment Architecture
Request flow: Browser → GitHub Pages (static frontend) → Fly.io API → Fly Postgres, with token settlement going from the API to Solana devnet.
| Component | Service | Configuration |
| Frontend | GitHub Pages | Static Vite build output, served over HTTPS |
| API | Fly.io | Docker container (fly.toml); Drizzle migrations run automatically at release time |
| Database | Fly Postgres | Managed PostgreSQL attached to the API app |
| Blockchain | Solana devnet | Anchor $DOUBLOON program; API talks to the cluster via RPC |
| Local Development | Dev mode | Same codebase settles token flows in the database — no chain required |
6.2 Authentication (Sign-In With Solana)
Passwordless, replay-proof wallet authentication:
Nonce challenge: The server issues a single-use nonce with a 5-minute TTL, stored in siws_nonces
Wallet signature: The player's wallet signs the challenge message client-side
Verification: The server verifies the ed25519 signature against the wallet's public key and consumes the nonce — a nonce can never be replayed
Session: The server issues its own HS256 JWT, valid for 7 days, used as the bearer token for all API calls
Abuse control: Auth endpoints are rate-limited like the rest of the API
6.3 Security Measures
Server-Side Validation: Every cost, reward, and prerequisite is checked on the server; the client cannot forge outcomes
Rate Limiting: Fixed-window limits per wallet and action (e.g., 10 arena fights per hour), backed by the rate_limits table
CORS Allow-List: The API accepts browser requests only from explicitly allowed origins
Exactly-Once Ledger: The token_ledger atomic-claim design prevents double-mints and double-burns under concurrency and retries
Collection Verification: NFT sync validates collection and update authority, so spoofed metadata names grant nothing
Transport Security: TLS on both GitHub Pages and Fly.io endpoints
7. Integration Points
7.1 External Services
Solana RPC: Cluster access for the Anchor program, delegate approvals, and NFT metadata fetches (devnet today)
Metaplex Token Metadata: Standard used to read and verify the original collections' on-chain metadata
Wallets: Phantom and Solflare via @solana/wallet-adapter
7.2 API Surface
A JSON REST API served by Hono. Key endpoint groups:
Authentication
Request nonce challenge - single-use, 5-minute TTL
Verify signature - validates ed25519 signature, issues 7-day JWT
Assets
Sync NFTs - fetch, verify, and map the wallet's Sea Rovers, Crypto Captains, and Crypto Coves
Profile and resources - balances, cove production claims
Gameplay
Voyages - start, status, and claim (raid claims trigger a boarding battle)
Arena - start a tiered PvE fight; returns the full battle log for replay
Jobs - unlock jobs, level with JP, purchase abilities, set primary/secondary
Token - onboarding grant and level-up burn, settled through the ledger
7.3 Future Work (Not Yet Built)
The following are on the roadmap but intentionally not part of the current architecture:
Next up: Deploy the Anchor program to devnet, mint test collections, open a public devnet beta
Gameplay: PvP raids, player marketplace, factions/alliances, seasonal content
Infrastructure: Blockchain indexers, CDN/edge caching, and dedicated real-time infrastructure will be added as the player base grows
8. Appendix
8.1 Technology Decision Matrix
| Decision | Option A | Option B | Choice |
| Smart Contract Framework | Anchor (Rust) | Native Rust | Anchor |
| Backend Framework | Hono (Node/TypeScript) | Express / NestJS | Hono |
| Data Access | Drizzle ORM | Prisma | Drizzle |
| Frontend Build | Vite SPA (React 19) | Next.js | Vite SPA |
| API Hosting | Fly.io (Docker) | AWS / GCP Kubernetes | Fly.io |
| Database | PostgreSQL | MongoDB | PostgreSQL |
8.2 Glossary
ATB: Active-Time Battle - the timing system driving combat turn order
JP: Job Points - currency earned in battle and voyages, spent on job levels and abilities
JWT: JSON Web Token - the signed session token issued after SIWS login
PDAs: Program Derived Addresses - deterministic Solana accounts owned by a program
RPC: Remote Procedure Call - interface to blockchain nodes
SIWS: Sign-In With Solana - wallet-signature authentication standard
SPL: Solana Program Library - the token standard $DOUBLOON is built on