سند پیادهسازی سامانه دارانو
1. مقدمه
این سند به تشریح جزئیات پیادهسازی سامانه دارانو میپردازد. برای درک معماری کلی سیستم، لطفاً به سند معماری مراجعه کنید. این سند شامل جزئیات فنی پیادهسازی، تکنولوژیهای استفاده شده، روشهای توسعه، و جنبههای عملیاتی است.
2. فناوریهای استفاده شده
2.1 Backend Services
| سرویس | زبان/Framework | نسخه | کاربرد اصلی |
|---|---|---|---|
| API Gateway | Go + Gin Router | Go 1.21+ | Routing, Auth, Rate Limiting |
| Auth Service | Go + GORM | Go 1.21+ | Authentication & Authorization |
| Wallet Service | Go + Stellar SDK | Go 1.21+ | Blockchain Operations |
| Market Service | Go + GORM | Go 1.21+ | Trading Engine |
| Wallet Streamer | Go + Horizon SDK | Go 1.21+ | Blockchain Event Listener |
| Admin Panel | Python + Django | Py 3.11+ | Management Interface |
چرا Go؟
- Performance بالا
- Concurrency عالی (Goroutines)
- مناسب برای Microservices
- Type-Safe و Compiled
- کتابخانههای عالی برای Blockchain (Stellar SDK)
چرا Django برای Admin Panel؟
- Admin Interface آماده
- ORM قدرتمند
- سرعت توسعه بالا
- امنیت Built-in
- Internal Network via docker isolation layer
- CSRF protection
- HTTP-only cookie
- RBAC Role checking
- Strong auditing community for vulnerabilities
2.2 Frontend
| Component | فناوری | نسخه | کاربرد |
|---|---|---|---|
| User UI | Next.js + React | Next 14+ | SSR + Client Rendering |
| Admin UI | Django Templates | Django 4+ | Server-Side Rendering |
| State Management | React Query + Zustand | Latest | API State + Local State |
| Styling | Tailwind CSS | v3 | Utility-First CSS |
| Charts | Recharts | Latest | Data Visualization |
2.3 Database & Storage
| فناوری | نسخه | کاربرد | پیکربندی کلیدی |
|---|---|---|---|
| PostgreSQL | 15+ | Primary Database | SSL Mode, Connection Pooling |
| Redis | 7+ | Cache, Session, Rate Limit | AOF Persistence, Cluster Mode |
| RabbitMQ | 3.12+ | Message Queue | Durable Queues, Message TTL |
2.4 Infrastructure
| فناوری | نسخه | کاربرد |
|---|---|---|
| Docker | 24+ | Containerization |
| Docker Compose | v2 | Multi-Container Orchestration |
| Traefik | v2.10 | Reverse Proxy + TLS |
| Cloudflare / ArvanCloudCDN | - | DNS + WAF + CDN |
| Prometheus | 2.45+ | Metrics Collection |
| Grafana | 10+ | Visualization |
| Alertmanager | 0.26+ | Alerting |
| Portainer | Latest | Container Management UI |
3. پیادهسازی سرویسها
3.1 ساختار پروژه (Project Structure)
darano/
├── services/
│ ├── api-gateway/
│ │ ├── cmd/ # Entry point
│ │ ├── internal/
│ │ │ ├── handlers/ # HTTP handlers
│ │ │ ├── middleware/ # JWT, CORS, etc.
│ │ │ ├── router/ # Route definitions
│ │ │ └── config/ # Configuration
│ │ ├── pkg/ # Shared packages
│ │ ├── go.mod
│ │ └── Dockerfile
│ │
│ ├── auth-service/
│ │ ├── cmd/
│ │ ├── internal/
│ │ │ ├── domain/ # Business logic
│ │ │ ├── repository/ # Data access
│ │ │ ├── service/ # Service layer
│ │ │ └── api/ # API handlers
│ │ ├── migrations/ # DB migrations
│ │ ├── go.mod
│ │ └── Dockerfile
│ │
│ ├── wallet-service/
│ │ ├── cmd/
│ │ ├── internal/
│ │ │ ├── blockchain/ # Stellar/Kuknos client
│ │ │ ├── domain/
│ │ │ ├── repository/
│ │ │ └── service/
│ │ ├── go.mod
│ │ └── Dockerfile
│ │
│ ├── market-service/
│ │ ├── cmd/
│ │ ├── internal/
│ │ │ ├── matching/ # Order matching engine
│ │ │ ├── domain/
│ │ │ ├── repository/
│ │ │ └── service/
│ │ ├── go.mod
│ │ └── Dockerfile
│ │
│ ├── wallet-streamer/
│ │ ├── cmd/
│ │ ├── internal/
│ │ │ ├── stream/ # Blockchain streaming
│ │ │ ├── processor/ # Event processing
│ │ │ └── repository/
│ │ ├── go.mod
│ │ └── Dockerfile
│ │
│ └── admin-panel/
│ ├── apps/
│ │ ├── users/
│ │ ├── market/
│ │ ├── wallet/
│ │ └── analytics/
│ ├── darano_admin/ # Django project
│ ├── requirements.txt
│ └── Dockerfile
│
├── frontend/
│ ├── ui/ # Next.js User Interface
│ │ ├── src/
│ │ │ ├── app/ # Next.js 14 App Router
│ │ │ ├── components/
│ │ │ ├── lib/
│ │ │ └── hooks/
│ │ ├── public/
│ │ ├── package.json
│ │ └── Dockerfile
│ │
├── deployments/
│ ├── docker-compose.yml
│ ├── docker-compose.prod.yml
│ └── traefik/
│ └── traefik.yml
│
└── monitoring/
├── prometheus/
│ └── prometheus.yml
├── grafana/
│ └── dashboards/
└── alertmanager/
└── alertmanager.yml
3.2 الگوهای پیادهسازی
Clean Architecture در Go Services
internal/
├── domain/ # Business Entities & Logic
│ ├── user.go
│ ├── wallet.go
│ └── errors.go
├── repository/ # Data Access Layer
│ ├── user_repo.go # Interface definition
│ └── postgres/
│ └── user_repo.go # PostgreSQL implementation
├── service/ # Business Service Layer
│ └── user_service.go
└── api/ # Presentation Layer
└── handlers/
└── user_handler.go
4. پیادهسازی امنیت
4.1 JWT Implementation
مشخصات Token:
{
"alg": "RS256",
"typ": "JWT"
}
{
"sub": "user_id",
"exp": 1234567890,
"iat": 1234567890,
"roles": ["user"],
"permissions": ["trade", "withdraw"]
}
Access Token: 15 دقیقه Refresh Token: 7 روز (ذخیره در Redis)
4.2 Password Hashing
- الگوریتم: bcrypt
- Cost Factor: 12
hash, err := bcrypt.GenerateFromPassword(
[]byte(password),
bcrypt.DefaultCost,
)
4.3 Key Management
Private Keys بلاکچین:
- ذخیره در HashiCorp Vault یا AWS KMS
- هرگز در کد یا Environment Variables
- Encryption at Rest
- Access Control سختگیرانه
مثال پیادهسازی:
type KeyManager interface {
GetPrivateKey(accountID string) (string, error)
StorePrivateKey(accountID, encryptedKey string) error
}
4.4 Rate Limiting
پیادهسازی با Redis:
func RateLimitMiddleware(limit int, window time.Duration) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := "rate:" + getUserIP(r)
count, _ := redisClient.Incr(ctx, key).Result()
if count == 1 {
redisClient.Expire(ctx, key, window)
}
if count > int64(limit) {
http.Error(w, "Rate limit exceeded", 429)
return
}
next.ServeHTTP(w, r)
})
}
}
محدودیتها: - API عمومی: 100 req/min - API احراز شده: 1000 req/min - API Admin: 5000 req/min
5. پیادهسازی بلاکچین (Blockchain Integration)
5.1 Stellar/Kuknos SDK Usage
import (
"github.com/stellar/go/clients/horizonclient"
"github.com/stellar/go/keypair"
"github.com/stellar/go/txnbuild"
)
type BlockchainClient struct {
client *horizonclient.Client
networkPassphrase string
}
func (bc *BlockchainClient) CreateAccount(publicKey string) error {
sourceKP := keypair.MustParseFull(bc.masterKey)
tx, err := txnbuild.NewTransaction(
txnbuild.TransactionParams{
SourceAccount: &sourceAccount,
Operations: []txnbuild.Operation{
&txnbuild.CreateAccount{
Destination: publicKey,
Amount: "2", // Minimum balance
},
},
BaseFee: txnbuild.MinBaseFee,
Timebounds: txnbuild.NewTimeout(300),
},
)
signedTx, _ := tx.Sign(bc.networkPassphrase, sourceKP)
_, err = bc.client.SubmitTransaction(signedTx)
return err
}
5.2 Token Issuance
برای حفظ امنیت کلید های میزبانی برای ایشو کردن توکن از Secret Manger در ریپازیتوی گیت استفاده شده
func (bc *BlockchainClient) IssueToken(
issuerSeed,
assetCode string,
amount string,
) error {
issuerKP := keypair.MustParseFull(issuerSeed)
asset := txnbuild.CreditAsset{
Code: assetCode,
Issuer: issuerKP.Address(),
}
// Set asset options
setOptions := &txnbuild.SetOptions{
SetFlags: []txnbuild.AccountFlag{
txnbuild.AuthRequired,
txnbuild.AuthRevocable,
},
}
// Payment operation for minting
payment := &txnbuild.Payment{
Destination: distributionAccount,
Asset: asset,
Amount: amount,
}
// Build and submit transaction
// ...
}
5.3 Streaming Events
func (s *WalletStreamer) StreamTransactions() {
cursor := s.getLastCursor()
err := s.client.StreamTransactions(
horizonclient.TransactionRequest{
Cursor: cursor,
},
func(tx horizon.Transaction) {
s.processTransaction(tx)
},
)
if err != nil {
log.Error("Stream error:", err)
time.Sleep(5 * time.Second) // Backoff
s.StreamTransactions() // Retry
}
}
func (s *WalletStreamer) processTransaction(tx horizon.Transaction) {
// Idempotency check
if s.isProcessed(tx.Hash) {
return
}
// Extract relevant operations
for _, op := range tx.Operations {
if payment, ok := op.(horizon.Payment); ok {
s.handlePayment(payment)
}
}
// Mark as processed
s.markProcessed(tx.Hash)
// Update cursor
s.updateCursor(tx.PagingToken)
}
6. پیادهسازی Database
6.1 Connection Pooling
PostgreSQL Configuration:
import "gorm.io/gorm"
func NewDatabase(dsn string) (*gorm.DB, error) {
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
PrepareStmt: true,
Logger: logger.Default.LogMode(logger.Info),
})
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
return db, err
}
6.2 Transactions
func (s *MarketService) ExecuteTrade(orderID, buyerID string) error {
return s.db.Transaction(func(tx *gorm.DB) error {
var order Order
if err := tx.First(&order, "id = ?", orderID).Error; err != nil {
return err
}
// Lock seller's tokens
if err := s.walletService.LockTokens(tx, order.SellerID, order.Amount); err != nil {
return err
}
// Deduct buyer's fiat
if err := s.walletService.DeductFiat(tx, buyerID, order.Price); err != nil {
return err
}
// Transfer tokens on blockchain
if err := s.blockchain.Transfer(order.SellerID, buyerID, order.Amount); err != nil {
return err // Rollback everything
}
// Update order status
order.Status = "filled"
return tx.Save(&order).Error
})
}
7. API Implementation
7.1 RESTful API Design
مثال Endpoint:
GET /api/v1/wallet/balance
POST /api/v1/wallet/transfer
GET /api/v1/market/orders
POST /api/v1/market/orders
DELETE /api/v1/market/orders/:id
7.2 Request/Response Format
Request:
POST /api/v1/market/orders
Authorization: Bearer <jwt>
Content-Type: application/json
{
"type": "sell",
"token": "DARANO",
"amount": "100",
"price": "50000"
}
Success Response:
HTTP/1.1 201 Created
Content-Type: application/json
{
"success": true,
"data": {
"order_id": "uuid-here",
"status": "open",
"created_at": "2025-01-01T10:00:00Z"
}
}
Error Response:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "موجودی کافی نیست",
"details": {
"required": "100",
"available": "50"
}
}
}
7.3 Validation
import "github.com/go-playground/validator/v10"
type CreateOrderRequest struct {
Type string `json:"type" validate:"required,oneof=buy sell"`
Token string `json:"token" validate:"required"`
Amount float64 `json:"amount" validate:"required,gt=0"`
Price float64 `json:"price" validate:"required,gt=0"`
}
func (h *Handler) CreateOrder(w http.ResponseWriter, r *http.Request) {
var req CreateOrderRequest
json.NewDecoder(r.Body).Decode(&req)
validate := validator.New()
if err := validate.Struct(req); err != nil {
respondError(w, 400, err)
return
}
// Process...
}
8. Deployment & DevOps
8.1 Docker Compose Setup
version: '3.8'
services:
traefik:
image: traefik:v2.10
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik/traefik.yml:/traefik.yml
- ./acme.json:/acme.json
networks:
- darano-network
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: darano
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- darano-network
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- darano-network
rabbitmq:
image: rabbitmq:3.12-management-alpine
environment:
RABBITMQ_DEFAULT_USER: ${MQ_USER}
RABBITMQ_DEFAULT_PASS: ${MQ_PASSWORD}
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- darano-network
api-gateway:
build: ./services/api-gateway
environment:
- DB_HOST=postgres
- REDIS_HOST=redis
- AUTH_SERVICE_URL=http://auth-service:8080
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.darano.ir`)"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
depends_on:
- postgres
- redis
networks:
- darano-network
auth-service:
build: ./services/auth-service
environment:
- DB_HOST=postgres
- REDIS_HOST=redis
depends_on:
- postgres
- redis
networks:
- darano-network
wallet-service:
build: ./services/wallet-service
environment:
- DB_HOST=postgres
- REDIS_HOST=redis
- BLOCKCHAIN_NETWORK=${BLOCKCHAIN_NETWORK}
- HORIZON_URL=${HORIZON_URL}
depends_on:
- postgres
- redis
networks:
- darano-network
# ... other services
networks:
darano-network:
driver: bridge
volumes:
postgres-data:
redis-data:
rabbitmq-data:
8.2 CI/CD Pipeline
GitHub Actions مثال:
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker Images
run: |
docker build -t darano/api-gateway:${{ github.sha }} ./services/api-gateway
docker build -t darano/auth-service:${{ github.sha }} ./services/auth-service
- name: Push to Registry
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push darano/api-gateway:${{ github.sha }}
docker push darano/auth-service:${{ github.sha }}
- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/darano
docker-compose pull
docker-compose up -d
8.3 Monitoring Setup
Prometheus Configuration:
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'api-gateway'
static_configs:
- targets: ['api-gateway:8080']
metrics_path: '/metrics'
- job_name: 'auth-service'
static_configs:
- targets: ['auth-service:8080']
- job_name: 'wallet-service'
static_configs:
- targets: ['wallet-service:8080']
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
Alerting Rules:
# alerts.yml
groups:
- name: darano_alerts
interval: 30s
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.service }}"
- alert: HighResponseTime
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 5
for: 10m
labels:
severity: warning
annotations:
summary: "95th percentile response time > 5s"
9. Testing Strategy
9.1 Unit Tests
func TestUserService_CreateUser(t *testing.T) {
// Arrange
mockRepo := &MockUserRepository{}
service := NewUserService(mockRepo)
user := &domain.User{
Mobile: "09123456789",
}
mockRepo.On("Create", user).Return(nil)
// Act
err := service.CreateUser(user)
// Assert
assert.NoError(t, err)
mockRepo.AssertExpectations(t)
}
9.2 Integration Tests
func TestOrderExecution_Integration(t *testing.T) {
// Setup test database
db := setupTestDB(t)
defer teardownTestDB(t, db)
// Create test data
seller := createTestUser(t, db)
buyer := createTestUser(t, db)
order := createTestOrder(t, db, seller.ID)
// Execute trade
service := NewMarketService(db, walletService)
err := service.ExecuteTrade(order.ID, buyer.ID)
// Verify results
assert.NoError(t, err)
updatedOrder := getOrder(t, db, order.ID)
assert.Equal(t, "filled", updatedOrder.Status)
}
9.3 Load Testing
استفاده از k6:
import http from 'k6/http';
import { check } from 'k6';
export let options = {
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 0 },
],
};
export default function () {
let res = http.get('https://api.darano.ir/health');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
}
10. ریسکهای فنی و راهکارها
| ریسک | احتمال | تأثیر | راهکار پیادهسازی شده |
|---|---|---|---|
| اتصال به بلاکچین قطع شود | متوسط | بالا | Circuit Breaker + Retry with Exponential Backoff |
| سرور کیفپول Down شود | پایین | بالا | Docker Auto-Restart + Health Checks + Alerting |
| Data Desync بین DB و Blockchain | پایین | بالا | Blockchain as Source of Truth + Periodic Reconciliation |
| API Abuse / DDoS | بالا | بالا | Cloudflare WAF + Rate Limiting + IP Blacklisting |
| Database Performance Degradation | متوسط | متوسط | Connection Pooling + Indexing + Read Replicas + Query Optimization |
| Memory Leak در سرویسها | پایین | متوسط | Monitoring + Auto-Restart on High Memory + Code Review |
| Message Queue Full | پایین | متوسط | Backpressure + Dead Letter Queue + Monitoring |
| Secret Exposure | پایین | بالا | Vault/KMS + No Secrets in Code + Environment Variables |
| Blockchain Fork/Network Issues | پایین | بالا | Monitor Network Status + Manual Intervention Protocol |
| High Traffic on Token Sale | متوسط | متوسط | Horizontal Scaling + Queue System + Pre-sale Registration |
11. Performance Optimization
11.1 Caching Strategy
func (s *WalletService) GetBalance(userID string) (Balance, error) {
// Try cache first
cacheKey := fmt.Sprintf("balance:%s", userID)
if cached, err := s.cache.Get(cacheKey); err == nil {
var balance Balance
json.Unmarshal([]byte(cached), &balance)
return balance, nil
}
// Query blockchain
balance, err := s.blockchain.GetBalance(userID)
if err != nil {
return Balance{}, err
}
// Cache result (5 minutes TTL)
data, _ := json.Marshal(balance)
s.cache.Set(cacheKey, string(data), 5*time.Minute)
return balance, nil
}
11.2 Database Indexing
-- Critical indexes for performance
CREATE INDEX idx_orders_status ON orders(status) WHERE status = 'open';
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);
CREATE INDEX idx_transactions_user_time ON transactions(user_id, created_at DESC);
CREATE INDEX idx_wallets_user ON wallets(user_id);
-- Composite indexes for common queries
CREATE INDEX idx_orders_token_status ON orders(token_code, status);
11.3 Async Processing
func (s *MarketService) CreateOrder(order *Order) error {
// Save order synchronously
if err := s.repo.Create(order); err != nil {
return err
}
// Process notifications asynchronously
go func() {
s.notificationService.SendOrderCreated(order)
}()
// Publish event to queue
s.eventBus.Publish("order.created", order)
return nil
}
12. Security Implementation Details
12.1 SQL Injection Prevention
استفاده از Prepared Statements (GORM به صورت پیشفرض):
// ✅ Safe - using GORM
db.Where("mobile = ?", userInput).First(&user)
// ❌ Unsafe - never do this
db.Raw("SELECT * FROM users WHERE mobile = '" + userInput + "'").Scan(&user)
12.2 XSS Prevention
Backend: - Sanitization تمام Input ها - Content-Type Headers صحیح - CSP Headers
Frontend:
// React automatically escapes
<div>{userInput}</div> // Safe
// Dangerous
<div dangerouslySetInnerHTML={{__html: userInput}} /> // Avoid!
12.3 CORS Configuration
func CORSMiddleware() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "https://darano.ir")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
w.Header().Set("Access-Control-Max-Age", "3600")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
}
13. مدیریت نسخه و Release
| معیار | وضعیت فعلی | توضیحات |
|---|---|---|
| نسخه فعلی | v0.6 (B-Level) | نسخه توسعه و تست |
| Semantic Versioning | ✔ | Major.Minor.Patch |
| Git Branching | GitFlow | main, develop, feature/, hotfix/ |
| Changelog | ✔ | CHANGELOG.md مستند |
| Database Migrations | ✔ | Versioned migrations |
| API Versioning | /api/v1 | URL-based versioning |
| Backward Compatibility | Best Effort | تا حد امکان حفظ میشود |
| Rollback Strategy | ✔ | Docker tags + Database migration rollback |
14. استانداردهای رعایتشده
14.1 Security Standards
- ✅ OWASP Top 10: تمام موارد بررسی و پوشش داده شده
- ✅ Zero Trust Architecture: برای عملیات مدیریتی
- ✅ Principle of Least Privilege: حداقل دسترسی لازم
- ✅ Defense in Depth: امنیت چندلایه
- ✅ Secure by Default: تنظیمات امن به صورت پیشفرض
14.2 Code Standards
- ✅ Go Code Review Comments: استاندارد کد Go
- ✅ RESTful API Design: اصول REST
- ✅ 12-Factor App: اصول برنامههای Cloud-Native
- ✅ Clean Code: اصول کد تمیز
- ✅ SOLID Principles: اصول طراحی شیگرا
14.3 Compliance (در صورت نیاز)
- 🔄 PCI DSS: برای پردازش پرداخت (Compliance توسط Payment Gateway)
- 🔄 GDPR: حفاظت از دادههای شخصی (در صورت کاربران اروپایی)
- ✅ Data Residency: دادهها در ایران ذخیره میشوند