Deposit Flow Architecture¶
Детальный поток депозитов через HD Wallet архитектуру с мониторингом блокчейна.
HD Wallet Deposit Flow¶
sequenceDiagram
participant User as 👤 User
participant UserApp as 📱 User App
participant API as 🌐 API
participant HDService as 🏦 HD Wallet Service
participant Monitor as 👁️ Blockchain Monitor
participant Blockchain as ⛓️ Blockchain Network
participant Database as 🗄️ PostgreSQL
participant BalanceService as 💰 Balance Service
Note over User,BalanceService: Step 1: Deposit Address Generation
User->>UserApp: Request deposit address
UserApp->>API: GET /user/deposit-address
API->>HDService: GenerateDepositAddress(userID)
HDService->>HDService: Derive address from XPUB
HDService->>Database: Store address mapping
Database->>HDService: Address stored
HDService->>API: Return deposit address
API->>UserApp: Deposit address
UserApp->>User: Display deposit address + QR code
Note over User,BalanceService: Step 2: User Makes Deposit
User->>User: Copy deposit address
User->>Blockchain: Send USDC to deposit address
Blockchain->>Blockchain: Transaction included in block
Note over User,BalanceService: Step 3: Blockchain Monitoring
Monitor->>Monitor: Periodic block scan (every 15 seconds)
Monitor->>Blockchain: Query new blocks
Blockchain->>Monitor: Block data with transactions
Monitor->>Monitor: Filter transactions to monitored addresses
Monitor->>Database: Query monitored addresses (is_monitored = true)
Database->>Monitor: User mappings for monitored addresses
Note over User,BalanceService: Step 4: Transaction Processing
Monitor->>Database: Create pending transaction
Database->>Monitor: Transaction stored
Monitor->>Monitor: Verify transaction confirmations
alt Transaction Confirmed (3+ confirmations)
Monitor->>Database: Update transaction status to "confirmed"
Monitor->>BalanceService: ProcessDeposit(userID, amount)
BalanceService->>Database: Update user balance
Database->>BalanceService: Balance updated
BalanceService->>Monitor: Deposit processed
Monitor->>Database: Update transaction status to "processed"
Note over User,BalanceService: Step 5: User Notification
Monitor->>UserApp: WebSocket notification (if connected)
UserApp->>User: Show deposit success notification
else Transaction Failed
Monitor->>Database: Update transaction status to "failed"
Monitor->>UserApp: WebSocket notification (if connected)
UserApp->>User: Show deposit failed notification
end
HD Wallet Address Generation¶
graph TB
subgraph "HD Wallet Architecture"
MASTER["🔑 Master Private Key\n(Admin Only)"]
XPUB["📖 Extended Public Key\n(In Config)"]
subgraph "Address Derivation"
PATH["🛤️ Derivation Path\nm/44'/60'/0'/0/user_index"]
DERIVE[⚙️ Derive Function]
ADDR[📍 Deposit Address]
end
subgraph "Database Storage"
USER_MAP["👤 User Mapping\nuser_id → address"]
ADDR_MAP["📍 Address Mapping\naddress → user_id"]
MONITOR["👁️ Monitored Flag\nis_monitored column"]
end
end
MASTER -.-> XPUB
XPUB --> PATH
PATH --> DERIVE
DERIVE --> ADDR
ADDR --> USER_MAP
ADDR --> ADDR_MAP
ADDR --> MONITOR
classDef master fill:#FF6B6B,stroke:#E55B5B,color:#fff
classDef xpub fill:#4ECDC4,stroke:#45B7B8,color:#fff
classDef derive fill:#45B7D1,stroke:#3D8BDB,color:#fff
classDef storage fill:#FFA07A,stroke:#FF8C69,color:#fff
class MASTER master
class XPUB xpub
class PATH,DERIVE,ADDR derive
class USER_MAP,ADDR_MAP,MONITOR storage
Blockchain Monitoring Process¶
flowchart TD
START[🔄 Start Monitor] --> SCAN[🔍 Scan Latest Block]
SCAN --> BLOCK{New Block?}
BLOCK -->|No| WAIT[⏰ Wait 15 seconds]
WAIT --> SCAN
BLOCK -->|Yes| EXTRACT[📋 Extract Transactions]
EXTRACT --> FILTER[🔍 Filter Our Addresses]
FILTER --> FOUND{Relevant Tx Found?}
FOUND -->|No| WAIT
FOUND -->|Yes| VALIDATE[✅ Validate Transaction]
VALIDATE --> AMOUNT_CHECK{Amount > 0?}
AMOUNT_CHECK -->|No| IGNORE[❌ Ignore Transaction]
IGNORE --> WAIT
AMOUNT_CHECK -->|Yes| CONFIRM_CHECK[🔍 Check Confirmations]
CONFIRM_CHECK --> CONF_COUNT{Confirmations >= 3?}
CONF_COUNT -->|No| PENDING[⏳ Mark as Pending]
PENDING --> WAIT
CONF_COUNT -->|Yes| PROCESS[✅ Process Deposit]
PROCESS --> UPDATE_BALANCE[💰 Update Balance]
UPDATE_BALANCE --> NOTIFY[📢 Notify User]
NOTIFY --> WAIT
classDef process fill:#EBF5FB,stroke:#3498DB,color:#000
classDef decision fill:#FFF3CD,stroke:#856404,color:#000
classDef action fill:#D5F4E6,stroke:#27AE60,color:#000
classDef wait fill:#F8D7DA,stroke:#721C24,color:#000
class START,SCAN,EXTRACT,FILTER,VALIDATE,CONFIRM_CHECK,PROCESS,UPDATE_BALANCE,NOTIFY process
class BLOCK,FOUND,AMOUNT_CHECK,CONF_COUNT decision
class PENDING,IGNORE action
class WAIT wait
Database Schema for Deposits¶
erDiagram
USERS {
uuid id PK
string email
string status
timestamp created_at
timestamp updated_at
}
WALLETS {
uuid id PK
uuid user_id FK
string address
integer network_id
string type
string currency
decimal balance
decimal pending_balance
integer address_index
boolean is_hd_generated
boolean is_primary
boolean is_monitored
timestamp created_at
timestamp updated_at
}
TRANSACTIONS {
uuid id PK
uuid user_id FK
string type
decimal amount
string currency
string status
string blockchain_tx_hash
string from_address
string to_address
integer confirmations
timestamp created_at
timestamp updated_at
}
USER_BALANCES {
uuid id PK
uuid user_id FK
string currency
decimal available
decimal pending
decimal invested
decimal locked
timestamp updated_at
}
USERS ||--o{ WALLETS : has
USERS ||--o{ TRANSACTIONS : has
USERS ||--|| USER_BALANCES : has
Transaction Status State Machine¶
stateDiagram-v2
[*] --> Detected: Transaction found on blockchain
Detected --> Pending: Initial confirmation
Pending --> Confirmed: 3+ confirmations
Pending --> Failed: Transaction reverted
Confirmed --> Processing: Balance update started
Processing --> Processed: Balance updated successfully
Processing --> Failed: Balance update failed
Failed --> Retry: Manual retry
Retry --> Processing: Retry processing
Processed --> [*]: Final state
Failed --> [*]: Final state (manual intervention needed)
Deposit Processing Logic¶
flowchart TD
subgraph "Deposit Processing Pipeline"
DETECT[🔍 Detect Transaction]
VALIDATE[✅ Validate Transaction]
CONFIRM[🔍 Wait for Confirmations]
PROCESS[⚙️ Process Deposit]
UPDATE[💰 Update Balance]
NOTIFY[📢 Notify User]
end
subgraph "Error Handling"
RETRY[🔄 Retry Logic]
ALERT[🚨 Admin Alert]
MANUAL[👨💻 Manual Review]
end
DETECT --> VALIDATE
VALIDATE --> CONFIRM
CONFIRM --> PROCESS
PROCESS --> UPDATE
UPDATE --> NOTIFY
VALIDATE -->|Invalid| RETRY
CONFIRM -->|Failed| RETRY
PROCESS -->|Failed| RETRY
UPDATE -->|Failed| RETRY
RETRY -->|Max Retries| ALERT
ALERT --> MANUAL
MANUAL --> PROCESS
classDef pipeline fill:#E8F5E8,stroke:#4CAF50,color:#000
classDef error fill:#FFE8E8,stroke:#F44336,color:#000
class DETECT,VALIDATE,CONFIRM,PROCESS,UPDATE,NOTIFY pipeline
class RETRY,ALERT,MANUAL error
Admin Deposit Consolidation¶
sequenceDiagram
participant Admin as 🔧 Admin
participant AdminApp as 🛠️ Admin App
participant API as 🌐 API
participant HDService as 🏦 HD Wallet Service
participant MetaMask as 🦊 MetaMask
participant Blockchain as ⛓️ Blockchain
participant Database as 🗄️ Database
Note over Admin,Database: Step 1: Admin Checks Pending Deposits
Admin->>AdminApp: Open consolidation dashboard
AdminApp->>API: GET /admin/pending-deposits
API->>Database: Query pending deposits
Database->>API: List of deposits to consolidate
API->>AdminApp: Display pending deposits
AdminApp->>Admin: Show consolidation opportunities
Note over Admin,Database: Step 2: Admin Initiates Consolidation
Admin->>AdminApp: Click "Consolidate Deposits"
AdminApp->>API: POST /admin/consolidate-deposits
API->>HDService: PrepareConsolidationTransactions()
HDService->>HDService: Generate consolidation transactions
HDService->>API: Return transaction details
API->>AdminApp: Transaction details
Note over Admin,Database: Step 3: Admin Signs Transactions
AdminApp->>MetaMask: Request transaction signatures
MetaMask->>Admin: Show transaction details
Admin->>MetaMask: Approve transactions
MetaMask->>AdminApp: Signed transactions
AdminApp->>API: POST /admin/execute-consolidation
API->>Blockchain: Submit consolidation transactions
Blockchain->>API: Transaction hashes
Note over Admin,Database: Step 4: Update Database
API->>Database: Update transaction statuses
Database->>API: Updates confirmed
API->>AdminApp: Consolidation complete
AdminApp->>Admin: Show success notification
Implementation Details¶
HD Wallet Service¶
func (s *HDWalletService) GenerateDepositAddress(userID string) (string, error) {
// Get user's derivation index
index, err := s.getUserDerivationIndex(userID)
if err != nil {
return "", err
}
// Derive address from XPUB
derivationPath := fmt.Sprintf("m/44'/60'/0'/0/%d", index)
address, err := s.deriveAddressFromXPUB(s.config.GetXPUB(), derivationPath)
if err != nil {
return "", err
}
// Store address mapping with monitoring enabled
err = s.storeAddressMapping(userID, address, derivationPath, true)
if err != nil {
return "", err
}
return address, nil
}
Blockchain Monitor¶
func (m *BlockchainMonitor) ScanBlocks() {
ticker := time.NewTicker(15 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
latestBlock, err := m.client.GetLatestBlock()
if err != nil {
log.Error("Failed to get latest block", err)
continue
}
// Get monitored addresses from database
monitoredAddresses, err := m.getMonitoredAddresses()
if err != nil {
log.Error("Failed to get monitored addresses", err)
continue
}
transactions := m.extractRelevantTransactions(latestBlock, monitoredAddresses)
for _, tx := range transactions {
if err := m.processTransaction(tx); err != nil {
log.Error("Failed to process transaction", err)
}
}
}
}
}
func (m *BlockchainMonitor) getMonitoredAddresses() ([]string, error) {
query := `
SELECT address
FROM wallets
WHERE is_monitored = true
`
var addresses []string
err := m.db.Select(&addresses, query)
if err != nil {
return nil, fmt.Errorf("failed to get monitored addresses: %w", err)
}
return addresses, nil
}
Balance Update¶
func (s *BalanceService) ProcessDeposit(userID string, amount decimal.Decimal, currency string) error {
return s.db.Transaction(func(tx *sql.Tx) error {
// Get current balance
balance, err := s.getBalance(tx, userID, currency)
if err != nil {
return err
}
// Update available balance
balance.Available = balance.Available.Add(amount)
balance.UpdatedAt = time.Now()
// Save updated balance
return s.updateBalance(tx, balance)
})
}
Security Considerations¶
- XPUB Security: Extended public key безопасен для storage, не позволяет получить private keys
- Address Validation: Все сгенерированные адреса проверяются на корректность
- Confirmation Requirements: Минимум 3 подтверждения для обработки депозита
- Double Spending Protection: Проверка уникальности transaction hash
- Amount Validation: Проверка положительных сумм и корректных decimal значений
- Rate Limiting: Ограничение частоты запросов к blockchain RPC
- Monitoring Alerts: Автоматические уведомления при критических ошибках
Завершенный рефакторинг: Единая таблица wallets¶
Статус: ЗАВЕРШЕН (2025-07-16)
Источник: Wallet Repository Consolidation Analysis (supervisor/tasks/20250716-1730-wallet-repository-consolidation-analysis.md)
Решенные проблемы¶
Старая схема user_wallet_addresses с ограничением (user_id, wallet_type) не позволяла:
- Иметь депозитные адреса в разных сетях (Ethereum И Tron)
- Поддерживать множественные типы кошельков
- Легко добавлять новые сети (Solana, Polygon)
Все проблемы решены с помощью новой единой таблицы wallets.
Реализованное решение: Единая таблица wallets¶
CREATE TABLE wallets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
-- Основные поля кошелька
address VARCHAR(64) NOT NULL UNIQUE,
network_id INTEGER NOT NULL, -- 1 (Ethereum), 8453 (Base), 84532 (Base Sepolia), 11155111 (Ethereum Sepolia), 1337 (Hardhat)
type VARCHAR(20) NOT NULL, -- deposit, personal, trading
currency VARCHAR(10) NOT NULL DEFAULT 'USDC',
-- HD Wallet поля
derivation_path VARCHAR(255),
address_index INTEGER,
is_hd_generated BOOLEAN DEFAULT false,
-- Метаданные
label VARCHAR(100),
status VARCHAR(20) DEFAULT 'active',
is_primary BOOLEAN DEFAULT false,
is_monitored BOOLEAN DEFAULT true,
-- Временные метки
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
Преимущества нового подхода¶
-
Поддержка множественных сетей:
-
Упрощение архитектуры:
- Единый репозиторий вместо 4 разбросанных модулей
- Один интерфейс для всех типов кошельков
-
Простое добавление новых сетей
-
Легкая миграция данных:
Обновленная архитектура deposit flow¶
После рефакторинга deposit flow будет работать с единой таблицей wallets:
// Обновленный мониторинг адресов
func (m *BlockchainMonitor) getMonitoredAddresses(network string) ([]string, error) {
query := `
SELECT address
FROM wallets
WHERE is_monitored = true AND network_id = $1
`
var addresses []string
err := m.db.Select(&addresses, query, network)
return addresses, err
}
// Создание депозитного адреса
func (s *WalletService) CreateDepositWallet(userID string, networkID int) (*Wallet, error) {
wallet := &Wallet{
UserID: userID,
NetworkID: networkID,
Type: "deposit",
Currency: "USDC",
IsHDGenerated: true,
IsMonitored: true,
Status: "active",
}
return s.walletRepo.CreateWallet(ctx, wallet)
}
Результаты реализации¶
- Время реализации: ✅ Завершен за 1 день (планировалось 1-2 недели)
- Упрощение миграции: ✅ На 70% упрощена
- Поддержка новых сетей: ✅ Мгновенная (уже поддерживается Ethereum и Base)
- Миграция данных: ✅ 100% (109 кошельков перенесены из старой таблицы)
Совместимость¶
✅ Рефакторинг проведен с полным сохранением существующего API и функциональности. Все текущие deposit flow процессы работают без изменений.
Текущее состояние базы данных¶
- Старая таблица
user_wallet_addresses: ✅ Удалена после миграции - Новая таблица
wallets: ✅ Активна (109 записей) - Поддерживаемые сети: Ethereum, Base
- Типы кошельков: deposit, personal