/
kleara
/
KlearaFintech-MVP
Обзор
Документация
Войти
/
kleara
/
KlearaFintech-MVP
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
blockchain-api/server.js
480 строк
18 KB
Eugene Nefediev
Initial commit: Kleara MVP
05 фев 2026, 15:05
05 фев 2026, 15:05
ce56b07
Код
Авторство
О чём код?
const express = require('express'); const { Pool } = require('pg'); const cors = require('cors'); const winston = require('winston'); const app = express(); const port = 4000; // Логирование const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.Console({ format: winston.format.simple() }) ], }); // Middleware app.use(cors()); app.use(express.json()); // Подключение к PostgreSQL const pool = new Pool({ connectionString: process.env.POSTGRES_URL || 'postgresql://postgres:password123@postgres:5432/payments', }); // Health check app.get('/health', (req, res) => { res.json({ status: 'OK', service: 'blockchain-api', domain: 'kleara.net', timestamp: new Date().toISOString(), version: '2.0.0', mode: 'simulation' // Режим симуляции для MVP }); }); // Статус блокчейн сети (симуляция) app.get('/blockchain/status', async (req, res) => { try { const status = { network: 'Hyperledger Fabric', status: 'simulation_active', domain: 'kleara.net', organizations: [ { name: 'Russia', domain: 'russia.kleara.net', currency: 'RUB', peer: 'peer0.russia.kleara.net:7051' }, { name: 'China', domain: 'china.kleara.net', currency: 'CNY', peer: 'peer0.china.kleara.net:8051' }, { name: 'India', domain: 'india.kleara.net', currency: 'INR', peer: 'peer0.india.kleara.net:9051' } ], channel: 'kleara-channel', chaincode: 'payments', mode: 'simulation', timestamp: new Date().toISOString() }; res.json({ success: true, data: status }); } catch (error) { logger.error('Blockchain status error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Получить пулы ликвидности (симуляция) app.get('/blockchain/pools', async (req, res) => { try { // Симулируем данные пулов const pools = [ { countryCode: 'RU', currency: 'RUB', balance: 1000000.00, minBalance: 100000.00, country: 'Russia', domain: 'russia.kleara.net', peer: 'peer0.russia.kleara.net:7051' }, { countryCode: 'CN', currency: 'CNY', balance: 1000000.00, minBalance: 100000.00, country: 'China', domain: 'china.kleara.net', peer: 'peer0.china.kleara.net:8051' }, { countryCode: 'IN', currency: 'INR', balance: 1000000.00, minBalance: 100000.00, country: 'India', domain: 'india.kleara.net', peer: 'peer0.india.kleara.net:9051' } ]; res.json({ success: true, data: pools, mode: 'simulation', timestamp: new Date().toISOString() }); } catch (error) { logger.error('Get pools error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Создать блокчейн транзакцию (симуляция) app.post('/blockchain/transactions', async (req, res) => { try { const { contractId, fromCountry, toCountry, amount, currency, sender, receiver, postgresTxId } = req.body; if (!contractId || !fromCountry || !toCountry || !amount || !currency) { return res.status(400).json({ success: false, error: 'Missing required fields' }); } // Симулируем создание транзакции в блокчейне const blockchainTxId = `kleara_tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const timestamp = new Date().toISOString(); // Логируем симуляцию logger.info('Simulating blockchain transaction:', { contractId, fromCountry, toCountry, amount, currency, blockchainTxId, timestamp }); // Обновляем в PostgreSQL если есть ID if (postgresTxId) { await pool.query( 'UPDATE transactions SET blockchain_tx_id = $1, blockchain_status = $2 WHERE id = $3', [blockchainTxId, 'simulated_pending', postgresTxId] ); // Симулируем выполнение через 2 секунды setTimeout(async () => { try { await pool.query( 'UPDATE transactions SET blockchain_status = $1, status = $2 WHERE blockchain_tx_id = $3', ['simulated_completed', 'completed', blockchainTxId] ); logger.info(`Simulated blockchain execution completed for tx: ${blockchainTxId}`); } catch (error) { logger.error('Simulated execution error:', error); } }, 2000); } const response = { success: true, message: 'Transaction simulated in blockchain', data: { contractId, fromCountry, toCountry, amount: parseFloat(amount), currency, sender, receiver, blockchainTxId, timestamp, status: 'simulated_pending', mode: 'simulation', domain: 'kleara.net', execution_note: 'Will be automatically executed in 2 seconds (simulation)' } }; res.status(201).json(response); } catch (error) { logger.error('Create blockchain transaction error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Выполнить транзакцию в блокчейне (симуляция) app.post('/blockchain/transactions/:contractId/execute', async (req, res) => { try { const { contractId } = req.params; // Симулируем выполнение logger.info(`Simulating execution of contract: ${contractId}`); // Обновляем в PostgreSQL const updateResult = await pool.query( 'UPDATE transactions SET blockchain_status = $1, status = $2 WHERE blockchain_tx_id LIKE $3 RETURNING *', ['simulated_completed', 'completed', `%${contractId}%`] ); const executedTx = { contractId, status: 'completed', executedAt: new Date().toISOString(), blockchainProof: `kleara_proof_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, details: { fromPool: { country: req.body.fromCountry || 'RU', currency: req.body.currency || 'RUB', amount: -(req.body.amount || 0), domain: 'kleara.net' }, toPool: { country: req.body.toCountry || 'RU', currency: req.body.currency || 'RUB', amount: req.body.amount || 0, domain: 'kleara.net' }, liquidityPoolsUpdated: true, mode: 'simulation' }, affectedTransactions: updateResult.rows.length, mode: 'simulation' }; logger.info('Blockchain transaction simulated as executed:', executedTx); res.json({ success: true, message: 'Blockchain transaction executed (simulation)', data: executedTx }); } catch (error) { logger.error('Execute blockchain transaction error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Синхронизация с PostgreSQL app.post('/blockchain/sync', async (req, res) => { try { // Находим транзакции ожидающие блокчейн const pendingResult = await pool.query(` SELECT * FROM transactions WHERE blockchain_status IN ('pending_blockchain', 'not_sent') OR blockchain_status IS NULL LIMIT 20 `); const synced = []; for (const tx of pendingResult.rows) { const countryMap = { RUB: 'RU', CNY: 'CN', INR: 'IN' }; const fromCountry = countryMap[tx.currency] || 'RU'; const toCountry = 'RU'; // Для MVP const contractId = `kleara_contract_${tx.id}_${Date.now()}`; const blockchainTxId = `kleara_tx_${tx.id}_${Date.now()}`; // Симулируем отправку в блокчейн logger.info(`Syncing transaction ${tx.id} to blockchain simulation`); // Обновляем в PostgreSQL await pool.query( 'UPDATE transactions SET blockchain_tx_id = $1, blockchain_status = $2 WHERE id = $3', [blockchainTxId, 'simulated_synced', tx.id] ); synced.push({ postgresId: tx.id, contractId, blockchainTxId, fromCountry, toCountry, amount: tx.amount, currency: tx.currency, domain: 'kleara.net', status: 'simulated_synced', timestamp: new Date().toISOString() }); } res.json({ success: true, message: `Synced ${synced.length} transactions to blockchain simulation`, data: synced, mode: 'simulation' }); } catch (error) { logger.error('Sync error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Получить транзакцию из блокчейна (симуляция) app.get('/blockchain/transactions/:contractId', async (req, res) => { try { const { contractId } = req.params; // Пробуем найти в PostgreSQL const txResult = await pool.query( 'SELECT * FROM transactions WHERE blockchain_tx_id LIKE $1 OR id::text LIKE $2', [`%${contractId}%`, `%${contractId.split('_')[2] || ''}%`] ); if (txResult.rows.length === 0) { // Возвращаем симулированные данные const simulatedTx = { contractId, status: 'simulated_completed', amount: 1000.00, currency: 'RUB', fromCountry: 'RU', toCountry: 'RU', sender: 'simulated_sender@kleara.net', receiver: 'simulated_receiver@kleara.net', timestamp: new Date().toISOString(), executedAt: new Date(Date.now() - 60000).toISOString(), // 1 минута назад blockchainProof: `kleara_proof_${contractId}`, domain: 'kleara.net', mode: 'simulation', note: 'This is simulated blockchain data for MVP' }; return res.json({ success: true, data: simulatedTx, simulated: true }); } const tx = txResult.rows[0]; const countryMap = { RUB: 'RU', CNY: 'CN', INR: 'IN' }; const blockchainTx = { contractId, status: tx.blockchain_status || 'simulated_pending', amount: tx.amount, currency: tx.currency, fromCountry: countryMap[tx.currency] || 'RU', toCountry: 'RU', sender: tx.sender, receiver: tx.receiver, timestamp: tx.created_at, executedAt: tx.blockchain_status === 'simulated_completed' ? new Date().toISOString() : null, blockchainProof: tx.blockchain_tx_id, domain: 'kleara.net', postgresId: tx.id, mode: 'simulation' }; res.json({ success: true, data: blockchainTx }); } catch (error) { logger.error('Get transaction error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Интеграция с основным API app.post('/api/transactions/blockchain', async (req, res) => { try { const { transactionId } = req.body; if (!transactionId) { return res.status(400).json({ success: false, error: 'Transaction ID required' }); } // Находим транзакцию в PostgreSQL const txResult = await pool.query('SELECT * FROM transactions WHERE id = $1', [transactionId]); if (txResult.rows.length === 0) { return res.status(404).json({ success: false, error: 'Transaction not found' }); } const tx = txResult.rows[0]; const countryMap = { RUB: 'RU', CNY: 'CN', INR: 'IN' }; const fromCountry = countryMap[tx.currency] || 'RU'; const toCountry = 'RU'; const contractId = `kleara_contract_${tx.id}_${Date.now()}`; // Симулируем отправку в блокчейн const blockchainTxId = `kleara_tx_${tx.id}_${Date.now()}`; // Обновляем транзакцию await pool.query( 'UPDATE transactions SET blockchain_tx_id = $1, blockchain_status = $2 WHERE id = $3', [blockchainTxId, 'simulated_pending', tx.id] ); // Симулируем успешное выполнение через 3 секунды setTimeout(async () => { try { await pool.query( 'UPDATE transactions SET blockchain_status = $1, status = $2 WHERE blockchain_tx_id = $3', ['simulated_completed', 'completed', blockchainTxId] ); logger.info(`Simulated blockchain completion for transaction ${tx.id}`); } catch (error) { logger.error('Simulated completion error:', error); } }, 3000); res.json({ success: true, message: 'Transaction submitted to blockchain simulation', domain: 'kleara.net', mode: 'simulation', data: { postgres: { id: tx.id, sender: tx.sender, receiver: tx.receiver, amount: tx.amount, currency: tx.currency, status: 'pending_blockchain' }, blockchain: { contractId, blockchainTxId, fromCountry, toCountry, status: 'simulated_pending', execution_scheduled: '3 seconds', domain: 'kleara.net' } } }); } catch (error) { logger.error('Blockchain integration error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Получить статистику блокчейна app.get('/blockchain/stats', async (req, res) => { try { // Статистика из PostgreSQL const statsResult = await pool.query(` SELECT COUNT(*) as total_transactions, COUNT(CASE WHEN blockchain_status LIKE 'simulated_%' THEN 1 END) as blockchain_transactions, COUNT(CASE WHEN blockchain_status = 'simulated_completed' THEN 1 END) as completed_transactions, COUNT(CASE WHEN blockchain_status = 'simulated_pending' THEN 1 END) as pending_transactions, SUM(CASE WHEN blockchain_status = 'simulated_completed' THEN amount ELSE 0 END) as total_amount FROM transactions `); const stats = statsResult.rows[0]; res.json({ success: true, data: { network: 'kleara.net', mode: 'simulation', statistics: { totalTransactions: parseInt(stats.total_transactions), blockchainTransactions: parseInt(stats.blockchain_transactions), completedTransactions: parseInt(stats.completed_transactions), pendingTransactions: parseInt(stats.pending_transactions), totalAmount: parseFloat(stats.total_amount) || 0 }, pools: [ { country: 'RU', currency: 'RUB', simulated_balance: 1000000.00 }, { country: 'CN', currency: 'CNY', simulated_balance: 1000000.00 }, { country: 'IN', currency: 'INR', simulated_balance: 1000000.00 } ], timestamp: new Date().toISOString() } }); } catch (error) { logger.error('Blockchain stats error:', error); res.status(500).json({ success: false, error: error.message }); } }); app.listen(port, () => { logger.info(`🚀 Blockchain API (kleara.net) running on port ${port}`); logger.info(`✅ Health: http://localhost:${port}/health`); logger.info(`✅ Mode: Simulation (MVP)`); logger.info(`✅ Domain: kleara.net`); logger.info(`✅ Organizations: Russia (RUB), China (CNY), India (INR)`); });