Architecture Overview
System architecture, module design, and key patterns
High-Level Architecture
StarkFi follows a layered architecture with three entry points that share a common service layer:
┌──────────────────────────────────────────────────────────────────────────┐
│ StarkFi │
│ │
│ ┌──────────┐ ┌─────────────────────┐ ┌───────────────────────┐ │
│ │ CLI │ │ MCP Server │ │ Agent Skills │ │
│ │ (30+ │ │ (27 tools) │ │ (10 workflows) │ │
│ │ commands)│ │ stdio transport │ │ npx starkfi@latest │ │
│ └────┬─────┘ └──────────┬──────────┘ └──────────┬────────────┘ │
│ │ │ │ │
│ └──────────────────────┼───────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Service Layer │ │
│ │ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌──────────┐ │ │
│ │ │ Fibrous │ │ Staking │ │ Vesu │ │ Batch │ │ │
│ │ │ Swap │ │ Lifecycle│ │ V2 │ │ Multicall│ │ │
│ │ └────┬─────┘ └────┬─────┘ └───┬────┘ └────┬─────┘ │ │
│ │ └──────────────┴────────────┴────────────┘ │ │
│ │ │ │ │
│ │ ┌───────────────┴───────────────────────────┐ │ │
│ │ │ Starkzap SDK (starkzap v1.0.0) │ │ │
│ │ │ Wallet · TxBuilder · Tokens · Paymaster │ │ │
│ │ └───────────────┬───────────────────────────┘ │ │
│ └───────────────────────┼──────────────────────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────┐ ┌──────────────────────┐ │
│ │ Auth Server (Hono + Privy TEE) │ │ AVNU Paymaster │ │
│ │ Email OTP · Wallet · Sign · Gas │ │ Gas Abstraction │ │
│ └──────────────────────────────────────┘ └──────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────┐
│ Starknet (L2) │
└──────────────────┘Directory Structure
src/
├── index.ts # CLI entry point (Commander.js)
├── commands/ # 9 command groups
│ ├── auth/ # login, verify, logout
│ ├── wallet/ # address, balance, send, deploy
│ ├── trade/ # trade, multi-swap, status
│ ├── staking/ # stake, unstake, rewards, pools, validators, stake-status
│ ├── lending/ # lend-pools, lend-supply, lend-withdraw, lend-borrow, lend-repay, lend-close, lend-status
│ ├── batch/ # batch multicall
│ ├── portfolio/ # portfolio dashboard
│ ├── config/ # config subcommands
│ └── chain/ # tx-status, mcp-start
├── services/ # 11 service modules
│ ├── starkzap/ # SDK client initialization + config
│ ├── fibrous/ # DEX routing, calldata, pricing
│ ├── vesu/ # Lending pool API + on-chain operations
│ ├── staking/ # Validator resolution + pool operations
│ ├── tokens/ # Token resolution + balance queries
│ ├── batch/ # Multicall composition via TxBuilder
│ ├── simulate/ # Transaction simulation (fee estimation)
│ ├── portfolio/ # Aggregated DeFi overview
│ ├── auth/ # Session management (JWT persistence)
│ ├── api/ # Backend API client
│ └── config/ # Configuration persistence
├── mcp/ # MCP server layer
│ ├── server.ts # Server setup + stdio transport
│ ├── tools/ # 7 tool registration files (Zod schemas)
│ └── handlers/ # 9 domain handlers + context + utils
└── lib/ # 12 shared utilities
├── errors.ts # ErrorCode enum + StarkfiError class
├── parse-starknet-error.ts # Cairo hex decoding + error map
├── retry.ts # Exponential backoff retry
├── concurrency.ts # Sliding-window concurrent execution
├── fetch.ts # Fetch with AbortController timeout
├── format.ts # Table, result, and error formatting
├── cli-helpers.ts # runCommand wrapper + outputResult
├── validation.ts # Address and input validation
├── types.ts # Shared TypeScript types
├── config.ts # Config file paths
├── brand.ts # CLI branding and colors
└── command.ts # Commander.js helpersKey Design Patterns
Service Layer Isolation
Each service module is self-contained — the Fibrous service doesn't know about Vesu, and vice versa. Cross-service composition happens only in dedicated orchestrators:
batchservice composes swap + stake + supply + send operationsportfolioservice aggregates data from tokens, staking, and lending services
Tool → Handler → Service (MCP)
MCP tools use a three-layer pattern that separates concerns:
Tool Registration (mcp/tools/) → Zod schema + description
↓
Handler (mcp/handlers/) → Input validation + orchestration
↓
Service (services/) → Business logic + SDK callsThis pattern keeps each layer testable and ensures MCP-specific concerns (schema validation, error formatting) don't leak into shared business logic.
Concurrent Sliding Window
Token balance queries and portfolio aggregation use a sliding-window concurrency pattern. Instead of issuing all RPC calls at once (which risks rate limiting) or processing sequentially (which is slow), a pool of workers pulls tasks from a shared queue:
// Example: Query 50 token balances with max 10 concurrent RPC calls
const balances = await runConcurrent(tokens, 10, async (token) => {
const balance = await wallet.balanceOf(token);
return balance.isZero() ? undefined : { token, balance };
});Error Recovery
All network operations use withRetry() for automatic retry with exponential backoff. Only retryable error codes (e.g., NETWORK_ERROR) trigger retries — domain errors (e.g., INSUFFICIENT_BALANCE) fail immediately. See the Error Handling page for details.
Transaction Simulation
Every transactional command supports --simulate (CLI) or simulation parameters (MCP). Simulation executes the transaction in a dry-run against the Starknet RPC, returning estimated fees and call count without spending gas.
Tech Stack
| Layer | Technology | Version |
|---|---|---|
| Core SDK | Starkzap | v1.0.0 |
| CLI Framework | Commander.js | v14.0.3 |
| MCP Protocol | @modelcontextprotocol/sdk | v1.27.1 |
| Schema Validation | Zod | v4.3.6 |
| Auth Server | Hono + Privy TEE | v4.12.7 |
| DEX Routing | Fibrous Aggregator | — |
| Lending Protocol | Vesu V2 | — |
| Gas Abstraction | AVNU Paymaster | — |
| Terminal UI | Chalk + Ora | v5.6.2 / v9.3.0 |
| TypeScript | TypeScript (strict mode) | v5.9.3 |
Last updated on