π Decentralized Real Estate Infrastructure | Backend API for blockchain-powered property transactions
PropChain Backend is a production-grade server-side infrastructure that enables the tokenization and trading of real estate assets through blockchain technology. Our API provides the core services needed to build decentralized real estate platforms, including smart contract integration, secure transaction processing, and comprehensive property management capabilities.
Built with enterprise-grade technologies, this backend serves as the foundation for Web3 real estate applications, enabling developers to create platforms where physical properties can be represented as digital assets and traded seamlessly using cryptocurrency.
- π Asset Tokenization: Transform physical real estate properties into tradable NFTs with legal compliance
- π° Crypto Transaction Processing: Secure, multi-chain cryptocurrency payment processing
- π Smart Contract Integration: Pre-built contracts for property ownership, transfers, and escrow
- π Property Management APIs: Complete CRUD operations for real estate listings and metadata
- π Web3 Authentication: Wallet-based user authentication with role-based access control
- πΎ Enterprise Data Storage: Scalable PostgreSQL database with migration support
- π Multi-Chain Support: Ethereum, Polygon, and BSC network compatibility
- π Real-Time Analytics: Property valuation trends and market insights
- π Search & Discovery: Advanced filtering and geospatial property search
- π± Mobile-Ready API: RESTful endpoints optimized for mobile applications
- π‘οΈ Security First: Built-in rate limiting, input validation, and audit logging
This backend is designed for:
- Real Estate Tech Companies building blockchain-based property platforms
- Property Investment Firms seeking fractional ownership solutions
- Blockchain Developers creating DeFi real estate applications
- Real Estate Agencies modernizing their transaction infrastructure
- FinTech Startups integrating real estate into their crypto ecosystems
Ensure you have the following installed:
- Node.js v18+ (LTS recommended) - Download
- npm v9+ or yarn v3+ package manager
- PostgreSQL v14+ - Download
- Redis v6+ - Download (for caching and session management)
- Git v2.30+ - Download
- Docker & Docker Compose (optional, for containerized setup)
Check your environment:
node --version # Should be v18.0.0 or higher
npm --version # Should be v9.0.0 or higher
psql --version # Should be PostgreSQL 14.0 or highergit clone https://github.com/MettaChain/PropChain-BackEnd.git
cd PropChain-BackEnd# Using npm (recommended)
npm install
# Or using yarn
yarn install# Copy environment template
cp .env.example .env
# Edit configuration (use your preferred editor)
nano .env
# or
code .envRequired Environment Variables:
DATABASE_URL- PostgreSQL connection string (e.g.,postgresql://user:pass@localhost:5432/propchain)JWT_SECRET- Secret key for JWT signing (generate:node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")JWT_REFRESH_SECRET- Secret for refresh tokens (different from JWT_SECRET)ENCRYPTION_KEY- 32-character encryption key for sensitive dataREDIS_URL- Redis connection string (e.g.,redis://localhost:6379)NODE_ENV- Environment (development/staging/production)
Optional but Recommended:
LOG_LEVEL- Logging verbosity (debug/info/warn/error)CORS_ORIGIN- CORS allowed origins (default: '*')PORT- Server port (default: 3000)MAX_LOGIN_ATTEMPTS- Max failed login attempts (default: 5)LOGIN_ATTEMPT_WINDOW- Time window for rate limiting in seconds (default: 600)
# Create PostgreSQL database
createdb propchain
# Or using psql if createdb is not in PATH
psql -U postgres -c "CREATE DATABASE propchain;"
# Run migrations
npm run migrate
# (Optional) Seed database with sample data
npm run db:seedVerify database connection:
npm run health # Should return 200 OKnpm run devThe server will start at http://localhost:3000 with:
- API endpoints at
http://localhost:3000/api/* - Swagger documentation at
http://localhost:3000/api - Health check at
http://localhost:3000/health
For a containerized development environment:
# Build Docker image
docker build -t propchain-backend:latest .
# Start with Docker Compose
docker-compose up
# Or run containers individually
docker run -p 3000:3000 \
-e DATABASE_URL=postgresql://user:pass@host:5432/propchain \
-e NODE_ENV=development \
propchain-backend:latestnpm run dev # Start development server with hot reload
npm run start:dev # Start with debug logging
npm run test:watch # Run tests in watch modeWatch mode will automatically restart the server when you make changes to TypeScript files.
# Build for production
npm run build # Compile TypeScript to JavaScript
# Start production server
npm start
# Verify service health
npm run health # Should return 200 OKProduction Checklist:
- Set
NODE_ENV=production - Use strong, randomly-generated JWT secrets
- Configure proper CORS origins
- Set up SSL/TLS certificates
- Configure database backups
- Set up monitoring and alerting
- Configure rate limiting appropriately
- Review security headers configuration
npm test # Run unit tests
npm run test:watch # Run tests in watch mode
npm run test:integration # Run integration tests
npm run test:e2e # Run end-to-end tests
npm run test:coverage # Generate coverage report
npm run lint # Check code style
npm run format # Auto-format code# Migrations
npm run migrate # Run pending migrations
npm run migrate:deploy # Deploy migrations (production)
npm run migrate:reset # Reset database (β οΈ deletes all data)
# Database tools
npm run db:seed # Seed with sample data
npm run db:studio # Open Prisma Studio UI
npm run db:backup # Backup database (runs scripts/backup.sh)
# Verification
npm run health # Health checkcurl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe"
}'Response:
{
"message": "User registered successfully. Please check your email for verification."
}curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123!"
}'Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "clx123...",
"email": "user@example.com",
"isVerified": false
}
}curl -X POST http://localhost:3000/api/auth/web3-login \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0x742d35Cc6634C0532925a3b844Bc59e4e7aa6cA6",
"signature": "0xabcdef..."
}'All protected endpoints require an authorization header:
curl -X GET http://localhost:3000/api/properties \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"curl -X POST http://localhost:3000/api/properties \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Luxury Apartment in Manhattan",
"description": "Beautiful 3-bedroom apartment with stunning city views",
"address": {
"street": "123 Fifth Avenue",
"city": "New York",
"state": "NY",
"zipCode": "10001",
"country": "USA"
},
"type": "APARTMENT",
"price": 2500000,
"bedrooms": 3,
"bathrooms": 2.5,
"areaSqFt": 2500,
"status": "AVAILABLE"
}'# Find 2-3 bedroom apartments under $500k in New York with pagination
curl -X GET "http://localhost:3000/api/properties?minBedrooms=2&maxBedrooms=3&type=APARTMENT&maxPrice=500000&city=New%20York&page=1&limit=20&sortBy=price&sortOrder=asc" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"# Find properties within 5km of coordinates (40.7128, -74.0060)
curl -X GET "http://localhost:3000/api/properties/search/nearby?latitude=40.7128&longitude=-74.0060&radiusKm=5" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"curl -X POST http://localhost:3000/api/auth/refresh-token \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "YOUR_REFRESH_TOKEN"
}'curl -X POST http://localhost:3000/api/auth/logout \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"- Access Token: 15 minutes (configurable via
JWT_EXPIRES_IN) - Refresh Token: 7 days (configurable via
JWT_REFRESH_EXPIRES_IN)
- Login Attempts: 5 attempts per 10 minutes per email/wallet
- API Requests: Configurable via
THROTTLE_LIMITandTHROTTLE_TTL
Passwords must contain:
- At least 8 characters
- One uppercase letter (A-Z)
- One lowercase letter (a-z)
- One number (0-9)
- One special character (!@#$%^&*)
- Always use HTTPS in production
- Keep secrets secure - never commit
.envfiles - Rotate keys regularly
- Monitor logs for suspicious activity
- Use strong passwords - encourage users to use password managers
- Enable email verification to prevent account takeover
- Implement 2FA for admin accounts
Error: ECONNREFUSED - connection refused on 127.0.0.1:5432
Solutions:
# Check if PostgreSQL is running
psql -U postgres -c "SELECT version();"
# On macOS with Homebrew
brew services start postgresql
# On Linux
sudo systemctl start postgresql
# Check DATABASE_URL is correct in .envError: Error: connect ECONNREFUSED 127.0.0.1:6379
Solutions:
# Start Redis server
redis-server
# Or check if Redis is running
redis-cli ping # Should return PONGError: Error: listen EADDRINUSE: address already in use :::3000
Solutions:
# Find process using port 3000
lsof -i :3000
# Kill the process
kill -9 <PID>
# Or use a different port
PORT=3001 npm run dev# Clear cache and rebuild
rm -rf dist/
npm run build
# Check TypeScript configuration
npx tsc --noEmitError: UnauthorizedException: Invalid token
Solutions:
- Ensure token is included in
Authorization: Bearer <token>header - Check token hasn't expired
- Verify
JWT_SECRETmatches on server - Try refreshing token with refresh endpoint
- Ethereum (Mainnet, Sepolia Testnet)
- Polygon (Mainnet, Mumbai Testnet)
- Binance Smart Chain (Mainnet, Testnet)
- Local Development (Hardhat Network)
# Database
DATABASE_URL=postgresql://user:pass@localhost:5432/propchain
# Blockchain
BLOCKCHAIN_NETWORK=sepolia
RPC_URL=https://sepolia.infura.io/v3/YOUR_PROJECT_ID
PRIVATE_KEY=your_private_key_here
# Security
JWT_SECRET=your_jwt_secret_key
API_KEY=your_api_key
# Services
REDIS_URL=redis://localhost:6379
WEB3_STORAGE_TOKEN=your_web3_storage_token- π API Reference - Complete REST API documentation with examples
- π Smart Contracts - Contract interfaces and integration guides
- π Deployment Guide - Production deployment best practices
- ποΈ Architecture - System design and technical architecture
PropChain-BackEnd/
βββ π src/
β βββ π controllers/ # API route handlers and request processing
β βββ π services/ # Business logic and external service integrations
β βββ π models/ # Database models and schemas (Prisma)
β βββ π middleware/ # Authentication, validation, and error handling
β βββ π utils/ # Helper functions and utilities
β βββ π config/ # Configuration management
β βββ π types/ # TypeScript type definitions
βββ π contracts/ # Smart contracts (Rust/Solidity)
βββ π migrations/ # Database migration files
βββ π tests/ # Unit, integration, and E2E tests
βββ π docs/ # Comprehensive documentation
βββ π scripts/ # Build, deployment, and utility scripts
βββ π .github/ # CI/CD workflows and issue templates
βββ π docker/ # Docker configuration files
- π€ Contributing Guide - How to contribute effectively
- π Code of Conduct - Community guidelines and standards
- π Issue Templates - Standardized issue reporting
- π‘ Feature Requests - Feature proposal template
- π Frontend Application - Client-side React/Next.js application
- π Security Audits - Third-party security audit reports
- π Performance Metrics - Benchmarks and optimization guides
- π Tutorials - Step-by-step integration tutorials
This example shows a complete authentication workflow from registration to authenticated API calls:
// 1. Register New User
const registerResponse = await fetch('http://localhost:3000/api/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'developer@example.com',
password: 'SecurePass123!',
firstName: 'Jane',
lastName: 'Developer',
}),
});
// User receives verification email
// 2. Login with email/password
const loginResponse = await fetch('http://localhost:3000/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'developer@example.com',
password: 'SecurePass123!',
}),
});
const { access_token, refresh_token, user } = await loginResponse.json();
console.log('Login successful for:', user.email);
// 3. Use access token for API requests
const propertiesResponse = await fetch('http://localhost:3000/api/properties?limit=10', {
headers: {
Authorization: `Bearer ${access_token}`,
},
});
const properties = await propertiesResponse.json();
// 4. Refresh token when expired
const refreshResponse = await fetch('http://localhost:3000/api/auth/refresh-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: refresh_token }),
});
const newTokens = await refreshResponse.json();
console.log('Token refreshed successfully');
// 5. Logout
const logoutResponse = await fetch('http://localhost:3000/api/auth/logout', {
method: 'POST',
headers: {
Authorization: `Bearer ${newTokens.access_token}`,
},
});
console.log('Logged out successfully');Complex property filtering with multiple criteria:
// Search for luxury properties with advanced filters
const searchParams = new URLSearchParams({
// Pagination
page: 1,
limit: 20,
// Text search
search: 'luxury penthouse',
// Property filters
type: 'APARTMENT',
status: 'AVAILABLE',
// Price range
minPrice: 1000000,
maxPrice: 5000000,
// Size filters
minBedrooms: 3,
maxBedrooms: 5,
// Location
city: 'Manhattan',
country: 'USA',
// Sorting
sortBy: 'price',
sortOrder: 'desc',
});
const response = await fetch(`http://localhost:3000/api/properties?${searchParams}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const { properties, total, page, totalPages } = await response.json();
console.log(`Found ${total} properties, showing page ${page} of ${totalPages}`);
properties.forEach(prop => {
console.log(`${prop.title}: $${prop.price.toLocaleString()}`);
});Find properties near a specific location:
// User coordinates: New York (40.7128, -74.0060)
const nearbyResponse = await fetch(
'http://localhost:3000/api/properties/search/nearby?' +
new URLSearchParams({
latitude: 40.7128,
longitude: -74.006,
radiusKm: 5, // Search within 5km
page: 1,
limit: 10,
}),
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);
const nearbyProperties = await nearbyResponse.json();
console.log(`Found ${nearbyProperties.length} properties within 5km`);Authenticate using blockchain wallet:
import { ethers } from 'ethers';
// Get user's wallet with MetaMask
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = provider.getSigner();
const walletAddress = await signer.getAddress();
// Create message to sign
const message = `Sign this message to login to PropChain at ${new Date().toISOString()}`;
const signature = await signer.signMessage(message);
// Login with Web3
const web3LoginResponse = await fetch('http://localhost:3000/api/auth/web3-login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
walletAddress: walletAddress,
signature: signature,
}),
});
const { access_token } = await web3LoginResponse.json();
console.log('Web3 login successful');
// If this is first time: account auto-created
// Use access_token for all subsequent API requestsMonitor and control user sessions:
// Get all active sessions
const sessionsResponse = await fetch('http://localhost:3000/api/auth/sessions', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const sessions = await sessionsResponse.json();
console.log(`Current user has ${sessions.length} active sessions`);
sessions.forEach((session, index) => {
console.log(`Session ${index + 1}:`);
console.log(` - IP: ${session.ip}`);
console.log(` - User Agent: ${session.userAgent}`);
console.log(` - Created: ${session.createdAt}`);
console.log(` - Expires in: ${session.expiresIn}ms`);
});
// Logout from specific device
const sessionIdToKill = sessions[0].id; // First session
const logoutDeviceResponse = await fetch(`http://localhost:3000/api/auth/sessions/${sessionIdToKill}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
console.log('Device logged out successfully');
// Logout from all devices
const logoutAllResponse = await fetch('http://localhost:3000/api/auth/sessions', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
console.log('All sessions terminated');- π Framework: NestJS (Node.js/TypeScript) - Enterprise-grade application framework
- ποΈ Database: PostgreSQL v14+ with Prisma ORM - Type-safe database access
- π Caching: Redis - High-performance caching and session storage
- π Message Queue: Bull Queue - Background job processing
- βοΈ Networks: Ethereum, Polygon, BSC - Multi-chain compatibility
- π Web3 Library: ethers.js - Modern Ethereum JavaScript library
- π Smart Contracts: Solidity (EVM) + Rust (Solana) - Cross-platform contracts
- π Wallet Integration: MetaMask, WalletConnect - Multi-wallet support
- π§ͺ Testing: Jest + Supertest - Comprehensive testing suite
- π API Docs: Swagger/OpenAPI 3.0 - Interactive API documentation
- π³ Containerization: Docker + Docker Compose - Consistent deployments
- π CI/CD: GitHub Actions - Automated testing and deployment
- π Monitoring: Prometheus + Grafana - Performance metrics and alerts
- π Authentication: JWT + Web3 signatures - Secure user verification
- π‘οΈ Security: Helmet, CORS, Rate Limiting - Production-grade security
- π Validation: class-validator - Request data validation
- π Auditing: Comprehensive audit logging for compliance
This project is licensed under the MIT License - see the LICENSE file for complete details.
- π Report Issues: GitHub Issues
- π§ Email Support: support@propchain.io
- π Documentation: docs.propchain.io
We welcome contributions! Please read our Contributing Guide to get started.
Quick contribution steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
β Star this repository if it helped you!
Made with β€οΈ by the PropChain Team