479 lines
12 KiB
Markdown
479 lines
12 KiB
Markdown
# Mining Service Architecture
|
||
|
||
## Overview
|
||
|
||
The Mining Service provides a gamified point mining system inspired by Pi Network, enabling users to accumulate Mining Points through daily engagement and community building.
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
graph TD
|
||
subgraph API["🌐 API Layer"]
|
||
Controllers[Controllers]
|
||
Commands[Commands]
|
||
Queries[Queries]
|
||
end
|
||
|
||
subgraph Domain["⚙️ Domain Layer"]
|
||
Miner[Miner Aggregate]
|
||
Circle[Circle Aggregate]
|
||
Referral[Referral Aggregate]
|
||
end
|
||
|
||
subgraph Infra["💾 Infrastructure Layer"]
|
||
EF[EF Core]
|
||
Redis[(Redis Cache)]
|
||
RabbitMQ[RabbitMQ]
|
||
end
|
||
|
||
subgraph Data["🗄️ Data Storage"]
|
||
DB[(PostgreSQL)]
|
||
end
|
||
|
||
API --> Domain
|
||
Domain --> Infra
|
||
EF --> DB
|
||
|
||
style API fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
|
||
style Domain fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
|
||
style Infra fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
|
||
style Data fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
|
||
```
|
||
|
||
## Architecture Patterns
|
||
|
||
### Domain-Driven Design (DDD)
|
||
|
||
- **Aggregates**: Miner, Circle, Referral
|
||
- **Entities**: MiningSession, MiningHistory, CircleMember
|
||
- **Value Objects**: MiningRate, MiningPoints, MiningSession
|
||
- **Domain Events**: MiningSessionStarted, PointsMined, CircleCompleted, ReferralActivated
|
||
|
||
### CQRS Pattern
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
flowchart LR
|
||
subgraph Write["📝 Commands"]
|
||
C1[StartMiningCommand]
|
||
C2[ClaimRewardCommand]
|
||
C3[CreateCircleCommand]
|
||
C4[InviteToCircleCommand]
|
||
C5[ApplyReferralCommand]
|
||
end
|
||
|
||
subgraph Read["📖 Queries"]
|
||
Q1[GetMinerStatusQuery]
|
||
Q2[GetMiningHistoryQuery]
|
||
Q3[GetCircleQuery]
|
||
Q4[GetReferralsQuery]
|
||
Q5[GetLeaderboardQuery]
|
||
end
|
||
|
||
style Write fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
|
||
style Read fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
|
||
```
|
||
|
||
## Domain Model
|
||
|
||
### Miner Aggregate
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
classDiagram
|
||
class Miner {
|
||
+Guid Id
|
||
+Guid UserId
|
||
+MinerRole Role
|
||
+decimal TotalMinedPoints
|
||
+MiningRate CurrentRate
|
||
+MiningSession ActiveSession
|
||
+MiningStreak Streak
|
||
+string ReferralCode
|
||
+Guid ReferredBy
|
||
+MinerStatus Status
|
||
+StartMiningSession()
|
||
+ClaimMiningReward()
|
||
+UpgradeRole()
|
||
+RecalculateMiningRate()
|
||
}
|
||
|
||
class MiningSession {
|
||
+Guid SessionId
|
||
+DateTime StartTime
|
||
+DateTime EndTime
|
||
+decimal AccumulatedPoints
|
||
+SessionStatus Status
|
||
}
|
||
|
||
class MiningRate {
|
||
+decimal BaseRate
|
||
+decimal CircleBonus
|
||
+decimal ReferralBonus
|
||
+decimal RoleBonus
|
||
+decimal StreakBonus
|
||
+decimal TotalRate
|
||
}
|
||
|
||
class MiningStreak {
|
||
+int CurrentStreak
|
||
+int LongestStreak
|
||
+DateTime LastMiningDate
|
||
+int FreezeTokens
|
||
+bool IsGracePeriod
|
||
+decimal BonusMultiplier
|
||
}
|
||
|
||
class MiningHistory {
|
||
+Guid Id
|
||
+decimal PointsEarned
|
||
+string Source
|
||
+DateTime EarnedAt
|
||
}
|
||
|
||
Miner "1" --> "0..1" MiningSession : has
|
||
Miner --> MiningRate : uses
|
||
Miner --> MiningStreak : tracks
|
||
Miner "1" --> "*" MiningHistory : tracks
|
||
```
|
||
|
||
### Circle Aggregate
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
classDiagram
|
||
class Circle {
|
||
+Guid Id
|
||
+Guid OwnerId
|
||
+string Name
|
||
+List~CircleMember~ Members
|
||
+decimal TrustScore
|
||
+decimal BonusMultiplier
|
||
+CircleStatus Status
|
||
+AddMember()
|
||
+RemoveMember()
|
||
+CalculateTrustScore()
|
||
+Validate()
|
||
}
|
||
|
||
class CircleMember {
|
||
+Guid Id
|
||
+Guid MinerId
|
||
+DateTime JoinedAt
|
||
+bool IsActive
|
||
}
|
||
|
||
Circle "1" --> "3..5" CircleMember : contains
|
||
```
|
||
|
||
### Referral Aggregate
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
classDiagram
|
||
class Referral {
|
||
+Guid Id
|
||
+Guid ReferrerId
|
||
+Guid ReferredId
|
||
+string ReferralCode
|
||
+decimal BonusRate
|
||
+bool IsActive
|
||
+int Level
|
||
+DateTime CreatedAt
|
||
+Activate()
|
||
+Deactivate()
|
||
+CalculateBonus()
|
||
}
|
||
```
|
||
|
||
## Mining Rate Formula
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
flowchart LR
|
||
Base["🎯 Base Rate<br/>0.25 MP/hour"] --> Multiply1((×))
|
||
Role["👤 Role Bonus<br/>+0-50%"] --> Multiply1
|
||
Multiply1 --> Multiply2((×))
|
||
Circle["🔵 Circle Bonus<br/>+25%"] --> Multiply2
|
||
Multiply2 --> Multiply3((×))
|
||
Referral["👥 Referral Bonus<br/>+25%/each"] --> Multiply3
|
||
Multiply3 --> Total["✅ Total Rate<br/>MP/hour"]
|
||
|
||
style Base fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:2px
|
||
style Role fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
|
||
style Circle fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
|
||
style Referral fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
|
||
style Total fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:3px
|
||
```
|
||
|
||
**Example Calculation:**
|
||
| Component | Value | Multiplier |
|
||
|-----------|-------|------------|
|
||
| Base Rate | 0.25 MP/hour | - |
|
||
| Role (Ambassador) | +25% | × 1.25 |
|
||
| Valid Circle | +25% | × 1.25 |
|
||
| 2 Referrals | +50% | × 1.50 |
|
||
| **Total** | **0.585 MP/hour** | **14.04 MP/day** |
|
||
|
||
## Database Schema
|
||
|
||
### ER Diagram
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
erDiagram
|
||
Miner ||--o{ MiningSession : has
|
||
Miner ||--o{ MiningHistory : tracks
|
||
Miner ||--o| Circle : owns
|
||
Circle ||--|{ CircleMember : contains
|
||
Miner ||--o{ Referral : refers
|
||
Miner ||--o| Referral : referredBy
|
||
|
||
Miner {
|
||
uuid Id PK
|
||
uuid UserId UK
|
||
string Role
|
||
decimal TotalMinedPoints
|
||
string ReferralCode UK
|
||
uuid ReferredBy FK
|
||
string Status
|
||
datetime CreatedAt
|
||
}
|
||
|
||
MiningSession {
|
||
uuid Id PK
|
||
uuid MinerId FK
|
||
datetime StartTime
|
||
datetime EndTime
|
||
decimal AccumulatedPoints
|
||
string Status
|
||
}
|
||
|
||
MiningHistory {
|
||
uuid Id PK
|
||
uuid MinerId FK
|
||
decimal PointsEarned
|
||
string Source
|
||
datetime EarnedAt
|
||
}
|
||
|
||
Circle {
|
||
uuid Id PK
|
||
uuid OwnerId FK
|
||
string Name
|
||
decimal TrustScore
|
||
decimal BonusMultiplier
|
||
string Status
|
||
}
|
||
|
||
CircleMember {
|
||
uuid Id PK
|
||
uuid CircleId FK
|
||
uuid MinerId FK
|
||
datetime JoinedAt
|
||
bool IsActive
|
||
}
|
||
|
||
Referral {
|
||
uuid Id PK
|
||
uuid ReferrerId FK
|
||
uuid ReferredId FK
|
||
string ReferralCode
|
||
decimal BonusRate
|
||
bool IsActive
|
||
int Level
|
||
}
|
||
```
|
||
|
||
### Key Indexes
|
||
|
||
| Index | Columns | Purpose |
|
||
|-------|---------|---------|
|
||
| `IX_Miners_UserId` | UserId | Fast lookup by user |
|
||
| `IX_Miners_ReferralCode` | ReferralCode | Referral code lookup |
|
||
| `IX_MiningSessions_MinerId_Status` | MinerId, Status | Active session check |
|
||
| `IX_Referrals_ReferrerId` | ReferrerId | Referral list |
|
||
|
||
## API Flow
|
||
|
||
### Start Mining Session
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
sequenceDiagram
|
||
participant Client as 📱 Client
|
||
participant API as 🌐 Mining API
|
||
participant Handler as ⚙️ CommandHandler
|
||
participant Miner as 👤 MinerAggregate
|
||
participant Calc as 🧮 RateCalculator
|
||
participant DB as 💾 PostgreSQL
|
||
participant Cache as ⚡ Redis
|
||
|
||
Client->>API: POST /api/v1/mining/start
|
||
API->>Handler: StartMiningCommand
|
||
Handler->>Miner: ValidateNoActiveSession()
|
||
Handler->>Calc: CalculateMiningRate()
|
||
Calc-->>Handler: MiningRate
|
||
Handler->>Miner: CreateSession(24h)
|
||
Miner->>DB: SaveSession()
|
||
Miner->>Cache: CacheSessionInfo(ttl: 24h)
|
||
API-->>Client: 200 OK { session_id, rate, end_time }
|
||
```
|
||
|
||
### Claim Mining Reward
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
sequenceDiagram
|
||
participant Client as 📱 Client
|
||
participant API as 🌐 Mining API
|
||
participant Handler as ⚙️ CommandHandler
|
||
participant Miner as 👤 MinerAggregate
|
||
participant DB as 💾 PostgreSQL
|
||
participant MQ as 📨 RabbitMQ
|
||
|
||
Client->>API: POST /api/v1/mining/claim
|
||
API->>Handler: ClaimRewardCommand
|
||
Handler->>Miner: GetActiveSession()
|
||
|
||
alt Session Completed
|
||
Miner->>Miner: CalculateEarnedPoints()
|
||
Miner->>Miner: AddToTotalPoints()
|
||
Miner->>DB: SaveMiningHistory()
|
||
Miner->>MQ: Publish PointsMinedEvent
|
||
API-->>Client: 200 OK { earned_points, total_points }
|
||
else Session Not Ready
|
||
API-->>Client: 400 Bad Request
|
||
end
|
||
```
|
||
|
||
## Inter-Service Communication
|
||
|
||
### Service Dependencies
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
graph TD
|
||
subgraph External["🔐 Authentication"]
|
||
IAM[IAM Service]
|
||
end
|
||
|
||
subgraph Core["⛏️ Mining Service"]
|
||
Mining[Mining Service]
|
||
end
|
||
|
||
subgraph Integration["🔗 Integrations"]
|
||
Social[Social Service]
|
||
Wallet[Wallet Service]
|
||
end
|
||
|
||
IAM -->|JWT Validation| Mining
|
||
Social <-->|Friend Data| Mining
|
||
Mining -->|Point Conversion| Wallet
|
||
|
||
style External fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
|
||
style Core fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:3px
|
||
style Integration fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
|
||
```
|
||
|
||
### Integration Events (RabbitMQ)
|
||
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
flowchart LR
|
||
subgraph Publishers["📤 Publishers"]
|
||
IAM[IAM Service]
|
||
Social[Social Service]
|
||
Mining1[Mining Service]
|
||
end
|
||
|
||
subgraph Events["📨 Events"]
|
||
E1[UserRegisteredEvent]
|
||
E2[FriendAddedEvent]
|
||
E3[PointsMinedEvent]
|
||
end
|
||
|
||
subgraph Consumers["📥 Consumers"]
|
||
Mining2[Mining Service]
|
||
Wallet[Wallet Service]
|
||
end
|
||
|
||
IAM --> E1 --> Mining2
|
||
Social --> E2 --> Mining2
|
||
Mining1 --> E3 --> Wallet
|
||
|
||
style Events fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
|
||
```
|
||
|
||
## Deployment
|
||
|
||
### Docker Compose
|
||
|
||
```yaml
|
||
mining-service:
|
||
build:
|
||
context: ../..
|
||
dockerfile: services/mining-service-net/Dockerfile
|
||
environment:
|
||
- DATABASE_URL=${MINING_DATABASE_URL}
|
||
- REDIS_URL=${REDIS_URL}
|
||
- RABBITMQ_URL=${RABBITMQ_URL}
|
||
- JWT_AUTHORITY=${IAM_SERVICE_URL}
|
||
labels:
|
||
- traefik.http.routers.mining.rule=PathPrefix(`/api/v1/mining`)
|
||
```
|
||
|
||
### Health Checks
|
||
|
||
| Endpoint | Check |
|
||
|----------|-------|
|
||
| `/health/live` | ✅ Service running |
|
||
| `/health/ready` | ✅ DB + Redis connected |
|
||
| `/health` | ✅ Full status |
|
||
|
||
## Security
|
||
|
||
### Rate Limiting
|
||
- 1 mining session start per 24 hours
|
||
- 10 circle invites per day
|
||
|
||
### Anti-Fraud
|
||
```mermaid
|
||
%%{init: {'theme':'dark'}}%%
|
||
flowchart TD
|
||
Request([🚀 Request]) --> Device{🔍 Device Check}
|
||
Device -->|New Device| Flag[⚠️ Flag for Review]
|
||
Device -->|Known| IP{🌐 IP Check}
|
||
IP -->|Suspicious| Block[❌ Block]
|
||
IP -->|Normal| KYC{🔐 KYC Verified?}
|
||
KYC -->|No| Limited[⚠️ Limited Features]
|
||
KYC -->|Yes| Full[✅ Full Access]
|
||
|
||
style Request fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
|
||
style Block fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
|
||
style Full fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
|
||
style Device fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
|
||
style IP fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
|
||
style KYC fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
|
||
```
|
||
|
||
## Caching Strategy (Redis)
|
||
|
||
| Key Pattern | TTL | Purpose |
|
||
|-------------|-----|---------|
|
||
| `session:{minerId}` | 24h | Active session cache |
|
||
| `rate:{minerId}` | 1h | Mining rate cache |
|
||
| `leaderboard:daily` | 5m | Leaderboard cache |
|
||
|
||
## Monitoring
|
||
|
||
### Metrics
|
||
- Mining sessions started/day
|
||
- Points mined total
|
||
- Active miners count
|
||
- Referral conversion rate
|
||
|
||
### Logging
|
||
- Serilog structured logging
|
||
- Correlation IDs for tracing
|
||
- Prometheus + Grafana integration
|