This MVP provides a complete end-to-end real estate tokenization platform with three integrated tiers:
property-token - A fully functional SEP-0041 compliant token contract
- Core state management: balances, allowances, total supply
- Admin functions: mint/burn for property managers
- Transfer mechanisms: direct transfers + delegated (approve/transfer_from)
- Property metadata: location, APY, property ID storage
Why this approach?
- Minimal but complete: 8 functions cover the MVP
- Testable: Included unit tests verify init, transfer, balance
- Extensible: Easy to add rent-distribution logic later
- Non-custodial: Users control their own tokens via Freighter
REST API with Stellar Integration
- Stellar SDK client: RPC calls, transaction building, network configuration
- PostgreSQL ORM: Auto-migrating schema for properties, users, transactions, portfolio
- SEP-10 authentication: Challenge-response wallet signing for non-custodial login
- CRUD endpoints: Properties management, portfolio tracking
Architecture:
Express App
├── Config (Stellar, DB)
├── Routes
│ ├── /health → Contract IDs, network status
│ ├── /api/properties → CRUD operations
│ └── /api/auth → SEP-10 challenge/verify
├── Services (WIP: contract interactions)
└── Utils (logging, database)
Database Schema:
properties: Listings with tokenomics (price, supply, APY)users: Wallet addresses with KYC statusportfolio: User token holdings per propertytransactions: Buy/sell history and rent distributions
User Interface with Wallet Integration
- Freighter integration: One-click wallet connect + SEP-10 signing
- Properties listing: Fetches from API, displays with fund progress
- API client: Type-safe fetch wrapper for all endpoints
- Hooks: Wallet state management (connect, login, logout)
- Responsive design: Mobile-first Tailwind CSS
User Flow:
- Land on homepage
- Click "Connect Wallet" → Freighter popup
- Sign SEP-10 challenge → JWT token issued
- Browse properties → API fetches from PostgreSQL
- (Phase 2) Click "Invest" → Smart contract mint + transfer
User (Browser)
↓
├─→ [Freighter Wallet]
│ ↓ (sign challenge)
├─→ Frontend (Next.js)
│ ├─ Wallet state (useStellarWallet hook)
│ ├─ Properties list
│ └─ Portfolio display
↓
└─→ Backend API (Express)
├─ /health → Network status
├─ /api/auth → Challenge/verify
├─ /api/properties → CRUD
└─ /api/portfolio → Holdings
↓
└─→ PostgreSQL
├─ properties table
├─ users table
├─ portfolio table
└─ transactions table
↓
└─→ Stellar Testnet
├─ Horizon API (account lookups)
├─ Soroban RPC (contract state)
└─ [Smart Contracts]
└─ property-token: balance_of, transfer, etc.
-
rent-distributor- Monthly rent collection & split -
installment-sale- Milestone-based payments -
title-registry- Government title integration -
co-ownership-dao- Voting on property decisions -
compliance- KYC/AML per jurisdiction -
oracle- XLM/USD price feeds -
escrow- General purpose escrow
- Real contract invocation service layer
- Rent payment tracking & distribution
- Marketplace/secondary trading
- Advanced KYC/AML checks
- IPFS document storage integration
- Admin dashboard
- Webhook notifications
- Token purchase flow (button wires to contract)
- Portfolio management dashboard
- Transaction history
- Rent distribution calendar
- KYC form & document upload
- Governance voting interface
- Mobile app (Flutter SDK)
- Create
backend/src/routes/newfeature.ts - Use existing pattern: import
query, create Router, add routes - Wire to
main.ts:app.use('/api/newfeature', newRoutes)
- Implement in
backend/src/services/contract.ts - Use Stellar SDK:
client.submitTransaction(tx)+SorobanServerfor RPC - Wire to route:
const result = await contractService.transfer(...)
- Create
frontend/src/components/NewFeature.tsx - Use
useStellarWallet()hook for wallet state - Use
apiFetch()fromlib/api.tsfor backend calls - Add to
app/page.tsxor new route
- Update
smartcontract/property-token/src/lib.rs cd smartcontract/property-token && cargo build --target wasm32-unknown-unknown --releasesoroban contract deploy --network testnet --source admin --wasm target/...- Add contract ID to
backend/.env
| Decision | Why |
|---|---|
| No Docker | Direct setup on testnet (faster dev cycle) |
| PostgreSQL | Off-chain metadata for properties/users |
| Freighter only | One wallet for MVP (xBull/WalletConnect later) |
| SEP-10 auth | Non-custodial, no password storage |
| Rust contracts | Soroban native, type-safe, auditable |
| Next.js 14 | Edge functions, type safety, fast refresh |
| Tailwind CSS | Utility-first for quick UI iteration |
| pnpm workspaces | Monorepo with shared types (future) |
- Backend starts:
curl http://localhost:3001/health - Database connects: Check logs in startup
- Frontend loads: http://localhost:3000 renders
- Wallet connect: Freighter popup appears
- API calls: Network tab shows
/api/propertiescall - Properties list: Renders from database
- Contract deployment: Copy contract ID to .env
- Contract invoke:
soroban contract invokeworks
- Database queries: Indexed on
stellar_address,property_id - API response: <200ms for list endpoints
- Wallet signing: ~3-5 seconds (depends on user)
- Contract state: Cached in frontend (no refresh needed)
- Bundle size: ~40KB gzipped (Next.js + Tailwind)
- Private keys: Never stored backend; Freighter handles signing
- JWT tokens: 7-day expiry, signed with JWT_SECRET
- CORS: Enabled (restrict to frontend domain in production)
- SQL injection: Parameterized queries via pg library
- Contract audit: TODO - external Soroban security firm
- Get it running locally - Follow QUICK_START.md
- Create sample property - POST to
/api/properties - Test wallet flow - Connect + sign in
- Deploy contract - See MVP_GUIDE.md step 7
- Implement purchase flow - Wire frontend button to contract mint
- Questions? Check
MVP_GUIDE.mdfor troubleshooting - Bugs? Open GitHub issue with error log
- Contribute? PRs welcome on
feat/mvp-implementation