feat(logging): replace 207 console.log/error/warn with pino structured logger (#58)
- Add pino + pino-pretty dependencies - Create src/utils/logger.js with env-based LOG_LEVEL - Replace all 207 console.log/error/warn calls across 46 source files - Remove [DEBUG], [ERROR] string prefixes (levels convey this) - Add pino redact for sensitive fields (mnemonic, privateKey, token, etc.) - Structured logging with context objects instead of string interpolation - NODE_ENV=production disables pino-pretty transport 49 files changed, 5601 insertions, 6056 deletions
This commit is contained in:
11197
package-lock.json
generated
11197
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,15 +11,16 @@
|
||||
"axios": "^1.7.7",
|
||||
"bip39": "^3.1.0",
|
||||
"bitcoinjs-lib": "^6.1.6",
|
||||
"csv-writer": "^1.6.0",
|
||||
"decompress": "^4.2.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"ecpair": "^2.1.0",
|
||||
"ethereumjs-util": "^7.1.5",
|
||||
"hdkey": "^2.1.0",
|
||||
"node-telegram-bot-api": "^0.64.0",
|
||||
"pino": "^8.21.0",
|
||||
"sqlite3": "^5.1.6",
|
||||
"tiny-secp256k1": "^2.2.3",
|
||||
"csv-writer": "^1.6.0"
|
||||
"tiny-secp256k1": "^2.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.2"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
if (!process.env.BOT_TOKEN) {
|
||||
console.error('FATAL: BOT_TOKEN environment variable is required');
|
||||
logger.fatal('BOT_TOKEN environment variable is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.ENCRYPTION_KEY || process.env.ENCRYPTION_KEY.length < 32) {
|
||||
console.error(
|
||||
'FATAL: ENCRYPTION_KEY environment variable is required and must be at least 32 characters. ' +
|
||||
logger.fatal(
|
||||
'ENCRYPTION_KEY environment variable is required and must be at least 32 characters. ' +
|
||||
'Generate one with: node -e "console.log(require(\'crypto\').randomBytes(32).toString(\'hex\'))"'
|
||||
);
|
||||
process.exit(1);
|
||||
@@ -17,7 +19,7 @@ const ADMIN_IDS = adminIdsRaw
|
||||
: [];
|
||||
|
||||
if (!adminIdsRaw) {
|
||||
console.warn('WARNING: ADMIN_IDS environment variable is not set. No admins configured.');
|
||||
logger.warn('ADMIN_IDS environment variable is not set. No admins configured.');
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import sqlite3 from 'sqlite3';
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
const DB_PATH = new URL('../../db/shop.db', import.meta.url).pathname;
|
||||
|
||||
const db = new sqlite3.Database(DB_PATH, sqlite3.OPEN_CREATE | sqlite3.OPEN_READWRITE, (err) => {
|
||||
if (err) {
|
||||
console.error('Database connection error:', err);
|
||||
logger.error({ err }, 'Database connection error');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('Connected to SQLite database');
|
||||
logger.info('Connected to SQLite database');
|
||||
});
|
||||
|
||||
db.run('PRAGMA foreign_keys = ON');
|
||||
@@ -28,13 +29,13 @@ db.getAsync = (sql, params = []) =>
|
||||
});
|
||||
|
||||
db.on('error', (err) => {
|
||||
console.error('Database error:', err);
|
||||
logger.error({ err }, 'Database error');
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
db.close((err) => {
|
||||
if (err) console.error('Error closing database:', err);
|
||||
else console.log('Database connection closed');
|
||||
if (err) logger.error({ err }, 'Error closing database');
|
||||
else logger.info('Database connection closed');
|
||||
process.exit(err ? 1 : 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import TelegramBot from "node-telegram-bot-api";
|
||||
import config from "../config/config.js";
|
||||
import logger from "../utils/logger.js";
|
||||
|
||||
const initBot = () => {
|
||||
try {
|
||||
const bot = new TelegramBot(config.BOT_TOKEN, {polling: true});
|
||||
console.log('Bot initialized successfully');
|
||||
logger.info('Bot initialized successfully');
|
||||
return bot;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize bot:', error);
|
||||
logger.error({ err: error }, 'Failed to initialize bot');
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import Validators from '../../utils/validators.js';
|
||||
import { isAdmin } from '../../middleware/auth.js';
|
||||
import userStates from "../../context/userStates.js";
|
||||
import bot from "../../context/bot.js";
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class AdminLocationHandler {
|
||||
|
||||
@@ -103,7 +104,7 @@ export default class AdminLocationHandler {
|
||||
}
|
||||
);
|
||||
} else {
|
||||
console.error('Error adding location:', error);
|
||||
logger.error({ err: error }, 'Error adding location');
|
||||
await bot.sendMessage(
|
||||
chatId,
|
||||
'❌ Error adding location. Please try again.',
|
||||
@@ -151,7 +152,7 @@ export default class AdminLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error getting IP:', error);
|
||||
logger.error({ err: error }, 'Error getting IP');
|
||||
await bot.sendMessage(chatId, '❌ Error getting IP address. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -232,7 +233,7 @@ export default class AdminLocationHandler {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error viewing locations:', error);
|
||||
logger.error({ err: error }, 'Error viewing locations');
|
||||
await bot.sendMessage(chatId, 'Error loading locations. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -275,7 +276,7 @@ export default class AdminLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDeleteLocation:', error);
|
||||
logger.error({ err: error }, 'Error in handleDeleteLocation');
|
||||
await bot.sendMessage(chatId, 'Error loading locations. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -320,7 +321,7 @@ export default class AdminLocationHandler {
|
||||
}
|
||||
} catch (error) {
|
||||
await db.runAsync('ROLLBACK');
|
||||
console.error('Error deleting location:', error);
|
||||
logger.error({ err: error }, 'Error deleting location');
|
||||
await bot.sendMessage(
|
||||
chatId,
|
||||
'❌ Error deleting location. Please try again.',
|
||||
|
||||
@@ -8,6 +8,7 @@ import WalletService from "../../services/walletService.js";
|
||||
import PurchaseService from "../../services/purchaseService.js";
|
||||
import userStates from "../../context/userStates.js";
|
||||
import Validators from '../../utils/validators.js';
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class AdminUserHandler {
|
||||
|
||||
@@ -83,7 +84,7 @@ export default class AdminUserHandler {
|
||||
|
||||
return message;
|
||||
} catch (error) {
|
||||
console.error('Error in calculateStatistics:', error);
|
||||
logger.error({ err: error }, 'Error in calculateStatistics');
|
||||
return 'Error loading statistics. Please try again.';
|
||||
}
|
||||
}
|
||||
@@ -147,7 +148,7 @@ export default class AdminUserHandler {
|
||||
|
||||
return { text: message, markup: keyboard };
|
||||
} catch (error) {
|
||||
console.error('Error in handleUserList:', error);
|
||||
logger.error({ err: error }, 'Error in handleUserList');
|
||||
return { text: 'Error loading user list. Please try again.' };
|
||||
}
|
||||
}
|
||||
@@ -279,7 +280,7 @@ export default class AdminUserHandler {
|
||||
parse_mode: 'HTML'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleViewUser:', error);
|
||||
logger.error({ err: error }, 'Error in handleViewUser');
|
||||
await bot.sendMessage(chatId, 'Error loading user details. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -312,7 +313,7 @@ export default class AdminUserHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDeleteUser:', error);
|
||||
logger.error({ err: error }, 'Error in handleDeleteUser');
|
||||
await bot.sendMessage(chatId, 'Error processing delete request. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -349,7 +350,7 @@ export default class AdminUserHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleConfirmDelete:', error);
|
||||
logger.error({ err: error }, 'Error in handleConfirmDelete');
|
||||
await bot.sendMessage(chatId, 'Error deleting user. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -382,7 +383,7 @@ export default class AdminUserHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleBlockUser:', error);
|
||||
logger.error({ err: error }, 'Error in handleBlockUser');
|
||||
await bot.sendMessage(chatId, 'Error processing block request. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -419,7 +420,7 @@ export default class AdminUserHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleConfirmBlock:', error);
|
||||
logger.error({ err: error }, 'Error in handleConfirmBlock');
|
||||
await bot.sendMessage(chatId, 'Error blocking user. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -450,7 +451,7 @@ export default class AdminUserHandler {
|
||||
|
||||
userStates.set(chatId, { action: "edit_bonus_balance", telegram_id: telegramId });
|
||||
} catch (error) {
|
||||
console.error('Error in handleEditUserBalance:', error);
|
||||
logger.error({ err: error }, 'Error in handleEditUserBalance');
|
||||
await bot.sendMessage(chatId, 'Error loading user wallets. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { isAdmin } from '../../middleware/auth.js';
|
||||
import LocationService from "../../services/locationService.js";
|
||||
import bot from "../../context/bot.js";
|
||||
import UserService from "../../services/userService.js";
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class AdminUserLocationHandler {
|
||||
|
||||
@@ -53,7 +54,7 @@ export default class AdminUserLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSetLocation:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetLocation');
|
||||
await bot.sendMessage(chatId, 'Error loading countries. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -89,7 +90,7 @@ export default class AdminUserLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSetCountry:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetCountry');
|
||||
await bot.sendMessage(chatId, 'Error loading cities. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -125,7 +126,7 @@ export default class AdminUserLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSetCity:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetCity');
|
||||
await bot.sendMessage(chatId, 'Error loading districts. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -158,7 +159,7 @@ export default class AdminUserLocationHandler {
|
||||
);
|
||||
} catch (error) {
|
||||
await db.runAsync('ROLLBACK');
|
||||
console.error('Error in handleSetDistrict:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetDistrict');
|
||||
await bot.sendMessage(chatId, 'Error updating location. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { isAdmin } from '../../middleware/auth.js';
|
||||
import WalletService from '../../services/walletService.js';
|
||||
import WalletUtils from '../../utils/walletUtils.js';
|
||||
import Validators from '../../utils/validators.js';
|
||||
import logger from '../../utils/logger.js';
|
||||
import fs from 'fs';
|
||||
import csvWriter from 'csv-writer';
|
||||
|
||||
@@ -95,7 +96,7 @@ export default class AdminWalletsHandler {
|
||||
// Отображаем первую страницу с пагинацией
|
||||
await this.displayWalletsPage(chatId, wallets, walletType, totalBalance, 0);
|
||||
} catch (error) {
|
||||
console.error('Error fetching wallets:', error);
|
||||
logger.error({ err: error }, 'Error fetching wallets');
|
||||
await bot.sendMessage(chatId, 'Failed to fetch wallets. Please try again later.');
|
||||
}
|
||||
}
|
||||
@@ -201,7 +202,7 @@ export default class AdminWalletsHandler {
|
||||
static async calculateCommission(walletType, totalBalance) {
|
||||
try {
|
||||
if (!config.COMMISSION_ENABLED) {
|
||||
console.log(`[${new Date().toISOString()}] Commissions disabled, returning 0`);
|
||||
logger.info('Commissions disabled, returning 0');
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -212,26 +213,25 @@ export default class AdminWalletsHandler {
|
||||
const commissionPercent = config.COMMISSION_PERCENT / 100;
|
||||
const commissionAmount = totalBalance * commissionPercent;
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Calculated commission for ${walletType}: ` +
|
||||
`${commissionAmount.toFixed(8)} (${config.COMMISSION_PERCENT}% of ${totalBalance.toFixed(2)})`);
|
||||
logger.info({ walletType, commissionPercent: config.COMMISSION_PERCENT, totalBalance: totalBalance.toFixed(2), commissionAmount: commissionAmount.toFixed(8) }, 'Calculated commission');
|
||||
|
||||
return commissionAmount;
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error calculating commission:`, error);
|
||||
logger.error({ err: error, walletType }, 'Error calculating commission');
|
||||
throw new Error(`Failed to calculate commission: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
static async checkCommissionBalance(walletType, requiredAmount) {
|
||||
try {
|
||||
console.log(`[${new Date().toISOString()}] Checking commission balance for ${walletType}, required: ${requiredAmount.toFixed(8)}`);
|
||||
logger.info({ walletType, requiredAmount: requiredAmount.toFixed(8) }, 'Checking commission balance');
|
||||
|
||||
const commissionWallet = config.COMMISSION_WALLETS[walletType];
|
||||
if (!commissionWallet) {
|
||||
throw new Error(`Commission wallet not configured for ${walletType}`);
|
||||
}
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Using commission wallet: ${commissionWallet}`);
|
||||
logger.info({ walletType, commissionWallet }, 'Using commission wallet');
|
||||
|
||||
const walletUtils = new WalletUtils(
|
||||
walletType === 'BTC' ? commissionWallet : null,
|
||||
@@ -244,30 +244,30 @@ export default class AdminWalletsHandler {
|
||||
let balance;
|
||||
switch (walletType) {
|
||||
case 'BTC':
|
||||
console.log(`[${new Date().toISOString()}] Getting BTC balance`);
|
||||
logger.info('Getting BTC balance');
|
||||
balance = await walletUtils.getBtcBalance();
|
||||
break;
|
||||
case 'LTC':
|
||||
console.log(`[${new Date().toISOString()}] Getting LTC balance`);
|
||||
logger.info('Getting LTC balance');
|
||||
balance = await walletUtils.getLtcBalance();
|
||||
break;
|
||||
case 'ETH':
|
||||
console.log(`[${new Date().toISOString()}] Getting ETH balance`);
|
||||
logger.info('Getting ETH balance');
|
||||
balance = await walletUtils.getEthBalance();
|
||||
break;
|
||||
case 'USDT':
|
||||
console.log(`[${new Date().toISOString()}] Getting USDT balance`);
|
||||
logger.info('Getting USDT balance');
|
||||
balance = await walletUtils.getUsdtErc20Balance();
|
||||
break;
|
||||
case 'USDC':
|
||||
console.log(`[${new Date().toISOString()}] Getting USDC balance`);
|
||||
logger.info('Getting USDC balance');
|
||||
balance = await walletUtils.getUsdcErc20Balance();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported wallet type: ${walletType}`);
|
||||
}
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Commission wallet balance: ${balance.toFixed(8)} ${walletType}`);
|
||||
logger.info({ walletType, balance: balance.toFixed(8) }, 'Commission wallet balance');
|
||||
|
||||
const result = {
|
||||
balance,
|
||||
@@ -275,10 +275,10 @@ export default class AdminWalletsHandler {
|
||||
difference: balance - requiredAmount
|
||||
};
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Commission check result:`, result);
|
||||
logger.info({ result }, 'Commission check result');
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error checking commission balance:`, error);
|
||||
logger.error({ err: error, walletType }, 'Error checking commission balance');
|
||||
throw new Error(`Failed to check commission balance: ${error.message}`);
|
||||
}
|
||||
}
|
||||
@@ -290,7 +290,7 @@ export default class AdminWalletsHandler {
|
||||
// Используем регулярное выражение для извлечения номера страницы
|
||||
const match = action.match(/next_page_(.+)_(\d+)/) || action.match(/prev_page_(.+)_(\d+)/);
|
||||
if (!match) {
|
||||
console.error('Invalid pagination action:', action);
|
||||
logger.error({ action }, 'Invalid pagination action');
|
||||
await bot.sendMessage(chatId, 'Invalid pagination action. Please try again.');
|
||||
return;
|
||||
}
|
||||
@@ -316,7 +316,7 @@ export default class AdminWalletsHandler {
|
||||
// Отображаем страницу с учетом пагинации
|
||||
await this.displayWalletsPage(chatId, wallets, walletType, totalBalance, pageNumber);
|
||||
} catch (error) {
|
||||
console.error('Error fetching wallets:', error);
|
||||
logger.error({ err: error }, 'Error fetching wallets');
|
||||
await bot.sendMessage(chatId, 'Failed to fetch wallets. Please try again later.');
|
||||
}
|
||||
}
|
||||
@@ -332,7 +332,7 @@ export default class AdminWalletsHandler {
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(`[${new Date().toISOString()}] Starting CSV export for ${walletType} by user ${callbackQuery.from.id}`);
|
||||
logger.info({ walletType, userId: callbackQuery.from.id }, 'Starting CSV export');
|
||||
|
||||
// Удаляем предыдущее сообщение перед отправкой нового
|
||||
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
|
||||
@@ -341,24 +341,24 @@ export default class AdminWalletsHandler {
|
||||
const wallets = await WalletService.getWalletsByType(walletType);
|
||||
|
||||
if (wallets.length === 0) {
|
||||
console.log(`[${new Date().toISOString()}] No wallets found for ${walletType}`);
|
||||
logger.info({ walletType }, 'No wallets found for export');
|
||||
await bot.sendMessage(chatId, `No wallets found for ${walletType}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Рассчитываем общий баланс
|
||||
const totalBalance = await this.calculateTotalBalance(wallets);
|
||||
console.log(`[${new Date().toISOString()}] Total balance for ${walletType}: $${totalBalance.toFixed(2)}`);
|
||||
logger.info({ walletType, totalBalance: totalBalance.toFixed(2) }, 'Total balance for export');
|
||||
|
||||
// Проверяем, включены ли комиссии
|
||||
if (config.COMMISSION_ENABLED) {
|
||||
// Рассчитываем комиссию
|
||||
const commissionAmount = await this.calculateCommission(walletType, totalBalance);
|
||||
console.log(`[${new Date().toISOString()}] Commission amount: ${commissionAmount.toFixed(8)} ${walletType}`);
|
||||
logger.info({ walletType, commissionAmount: commissionAmount.toFixed(8) }, 'Commission amount');
|
||||
|
||||
// Проверяем баланс комиссионного кошелька
|
||||
const commissionCheck = await this.checkCommissionBalance(walletType, commissionAmount);
|
||||
console.log(`[${new Date().toISOString()}] Commission wallet balance: ${commissionCheck.balance.toFixed(8)} ${walletType}`);
|
||||
logger.info({ walletType, commissionBalance: commissionCheck.balance.toFixed(8) }, 'Commission wallet balance');
|
||||
|
||||
if (commissionCheck.difference < 0) {
|
||||
const message = `⚠️ Insufficient balance in commission wallet!\n` +
|
||||
@@ -376,7 +376,7 @@ export default class AdminWalletsHandler {
|
||||
]
|
||||
};
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Insufficient commission balance for ${walletType}`);
|
||||
logger.warn({ walletType }, 'Insufficient commission balance');
|
||||
await bot.sendMessage(chatId, message, { reply_markup: keyboard });
|
||||
return;
|
||||
}
|
||||
@@ -412,7 +412,7 @@ export default class AdminWalletsHandler {
|
||||
try {
|
||||
mnemonic = await WalletService.decryptMnemonic(wallet.mnemonic, wallet.user_id);
|
||||
} catch (error) {
|
||||
console.error('Error decrypting mnemonic:', error);
|
||||
logger.error({ err: error }, 'Error decrypting mnemonic');
|
||||
mnemonic = '[DECRYPTION FAILED]';
|
||||
}
|
||||
}
|
||||
@@ -441,17 +441,17 @@ export default class AdminWalletsHandler {
|
||||
});
|
||||
|
||||
await csv.writeRecords(walletsWithData);
|
||||
console.log(`[${new Date().toISOString()}] CSV file created at ${csvPath}`);
|
||||
logger.info({ csvPath }, 'CSV file created');
|
||||
|
||||
// Отправляем файл пользователю
|
||||
await bot.sendDocument(chatId, fs.createReadStream(csvPath));
|
||||
console.log(`[${new Date().toISOString()}] CSV file sent to user ${callbackQuery.from.id}`);
|
||||
logger.info({ userId: callbackQuery.from.id }, 'CSV file sent to user');
|
||||
|
||||
// Удаляем временный файл
|
||||
fs.unlinkSync(csvPath);
|
||||
console.log(`[${new Date().toISOString()}] Temporary CSV file deleted`);
|
||||
logger.info('Temporary CSV file deleted');
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error exporting wallets to CSV:`, error);
|
||||
logger.error({ err: error }, 'Error exporting wallets to CSV');
|
||||
await bot.sendMessage(chatId, 'Failed to export wallets to CSV. Please try again later.');
|
||||
}
|
||||
}
|
||||
@@ -467,7 +467,7 @@ export default class AdminWalletsHandler {
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(`[${new Date().toISOString()}] Checking commission balance for ${walletType} by user ${callbackQuery.from.id}`);
|
||||
logger.info({ walletType, userId: callbackQuery.from.id }, 'Checking commission balance');
|
||||
|
||||
// Удаляем предыдущее сообщение перед отправкой нового
|
||||
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
|
||||
@@ -478,16 +478,16 @@ export default class AdminWalletsHandler {
|
||||
|
||||
// Получаем все кошельки выбранного типа
|
||||
const wallets = await WalletService.getWalletsByType(walletType);
|
||||
console.log(`[${new Date().toISOString()}] Found ${wallets.length} wallets for ${walletType}`);
|
||||
logger.info({ walletType, walletCount: wallets.length }, 'Found wallets');
|
||||
|
||||
const totalBalance = await this.calculateTotalBalance(wallets);
|
||||
console.log(`[${new Date().toISOString()}] Total balance: $${totalBalance.toFixed(2)}`);
|
||||
logger.info({ totalBalance: totalBalance.toFixed(2) }, 'Total balance');
|
||||
|
||||
const commissionAmount = await this.calculateCommission(walletType, totalBalance);
|
||||
console.log(`[${new Date().toISOString()}] Commission amount: ${commissionAmount.toFixed(8)} ${walletType}`);
|
||||
logger.info({ walletType, commissionAmount: commissionAmount.toFixed(8) }, 'Commission amount');
|
||||
|
||||
const commissionCheck = await this.checkCommissionBalance(walletType, commissionAmount);
|
||||
console.log(`[${new Date().toISOString()}] Commission wallet balance: ${commissionCheck.balance.toFixed(8)} ${walletType}`);
|
||||
logger.info({ walletType, commissionBalance: commissionCheck.balance.toFixed(8) }, 'Commission wallet balance');
|
||||
|
||||
if (commissionCheck.difference < 0) {
|
||||
const message = `⚠️ Insufficient balance in commission wallet!\n` +
|
||||
@@ -505,19 +505,19 @@ export default class AdminWalletsHandler {
|
||||
]
|
||||
};
|
||||
|
||||
console.log(`[${new Date().toISOString()}] Insufficient commission balance for ${walletType}`);
|
||||
logger.warn({ walletType }, 'Insufficient commission balance');
|
||||
await bot.sendMessage(chatId, message, { reply_markup: keyboard });
|
||||
} else {
|
||||
// Если баланс достаточный, продолжаем экспорт
|
||||
console.log(`[${new Date().toISOString()}] Commission balance sufficient, proceeding with export`);
|
||||
logger.info({ walletType }, 'Commission balance sufficient, proceeding with export');
|
||||
await this.handleExportCSV(callbackQuery);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[${new Date().toISOString()}] Error checking commission balance:`, error);
|
||||
logger.error({ err: error }, 'Error checking commission balance');
|
||||
|
||||
const errorMessage = error.response?.data?.message || error.message;
|
||||
console.error(`[${new Date().toISOString()}] Error details:`, errorMessage);
|
||||
logger.error({ errorMessage }, 'Error details');
|
||||
|
||||
await bot.sendMessage(
|
||||
chatId,
|
||||
@@ -546,7 +546,7 @@ export default class AdminWalletsHandler {
|
||||
// Отображаем первую страницу с пагинацией
|
||||
await this.displayWalletsPage(chatId, wallets, walletType, totalBalance, 0);
|
||||
} catch (error) {
|
||||
console.error('Error in handleBackToWalletList:', error);
|
||||
logger.error({ err: error }, 'Error in handleBackToWalletList');
|
||||
await bot.sendMessage(chatId, 'An error occurred. Please try again later.');
|
||||
}
|
||||
}
|
||||
@@ -577,7 +577,7 @@ export default class AdminWalletsHandler {
|
||||
// Отправляем новое сообщение с клавиатурой
|
||||
await bot.sendMessage(chatId, 'Select wallet type:', keyboard);
|
||||
} catch (error) {
|
||||
console.error('Error in handleBackToWalletTypes:', error);
|
||||
logger.error({ err: error }, 'Error in handleBackToWalletTypes');
|
||||
await bot.sendMessage(chatId, 'An error occurred. Please try again later.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import LocationService from '../../../services/locationService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import Validators from '../../../utils/validators.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class CategoryAddHandler {
|
||||
|
||||
@@ -55,7 +56,7 @@ export default class CategoryAddHandler {
|
||||
if (error.code === 'SQLITE_CONSTRAINT') {
|
||||
await bot.sendMessage(chatId, 'This category already exists in this location.');
|
||||
} else {
|
||||
console.error('Error adding category:', error);
|
||||
logger.error({ err: error }, 'Error adding category');
|
||||
await bot.sendMessage(chatId, 'Error adding category. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { isAdmin } from '../../../middleware/auth.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import Validators from '../../../utils/validators.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class CategoryEditHandler {
|
||||
|
||||
@@ -49,7 +50,7 @@ export default class CategoryEditHandler {
|
||||
|
||||
userStates.delete(chatId);
|
||||
} catch (error) {
|
||||
console.error('Error updating category:', error);
|
||||
logger.error({ err: error }, 'Error updating category');
|
||||
await bot.sendMessage(chatId, 'Ошибка обновления категории. Пожалуйста, попробуйте снова.');
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import LocationService from '../../../services/locationService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import CategoryService from '../../../services/categoryService.js';
|
||||
import ProductService from '../../../services/productService.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class CategorySelectionHandler {
|
||||
|
||||
@@ -41,7 +42,7 @@ export default class CategorySelectionHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleCategorySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleCategorySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading products. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { isAdmin } from '../../../middleware/auth.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class CreateHandler {
|
||||
|
||||
@@ -49,7 +50,7 @@ export default class CreateHandler {
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleAddProduct:', error);
|
||||
logger.error({ err: error }, 'Error in handleAddProduct');
|
||||
await bot.sendMessage(chatId, 'Error preparing product import. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import db from '../../../config/database.js';
|
||||
import { isAdmin } from '../../../middleware/auth.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import ProductService from '../../../services/productService.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class DeleteHandler {
|
||||
|
||||
@@ -42,7 +43,7 @@ export default class DeleteHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDeleteUser:', error);
|
||||
logger.error({ err: error }, 'Error in handleDeleteUser');
|
||||
await bot.sendMessage(chatId, 'Error processing delete request. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -71,7 +72,7 @@ export default class DeleteHandler {
|
||||
await db.runAsync('COMMIT');
|
||||
} catch (e) {
|
||||
await db.runAsync('ROLLBACK');
|
||||
console.error('Error deleting product:', e);
|
||||
logger.error({ err: e }, 'Error deleting product');
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ export default class DeleteHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleConfirmDelete:', error);
|
||||
logger.error({ err: error }, 'Error in handleConfirmDelete');
|
||||
await bot.sendMessage(chatId, 'Error deleting product. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import LocationService from '../../../services/locationService.js';
|
||||
import CategoryService from '../../../services/categoryService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class DistrictHandler {
|
||||
|
||||
@@ -37,7 +38,7 @@ export default class DistrictHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleCitySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleCitySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading districts. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -82,7 +83,7 @@ export default class DistrictHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDistrictSelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleDistrictSelection');
|
||||
await bot.sendMessage(chatId, 'Error loading categories. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import fs from 'fs/promises';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import { validateProductName, validateProductPrice } from './productValidator.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class EditImportHandler {
|
||||
static async handleProductEditImport(msg) {
|
||||
@@ -85,7 +86,7 @@ export default class EditImportHandler {
|
||||
|
||||
userStates.delete(chatId);
|
||||
} catch (error) {
|
||||
console.error('Error importing products:', error);
|
||||
logger.error({ err: error }, 'Error importing products');
|
||||
await bot.sendMessage(chatId, 'Error importing products. Please check the data and try again.');
|
||||
await db.runAsync('ROLLBACK');
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { isAdmin } from '../../../middleware/auth.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import ProductService from '../../../services/productService.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class EditStartHandler {
|
||||
static async handleProductEdit(callbackQuery) {
|
||||
@@ -56,7 +57,7 @@ export default class EditStartHandler {
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleProductEdit:', error);
|
||||
logger.error({ err: error }, 'Error in handleProductEdit');
|
||||
await bot.sendMessage(chatId, 'Error loading product details. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import fs from 'fs/promises';
|
||||
import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import ProductValidator from './productValidator.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class ImportHandler {
|
||||
|
||||
@@ -47,7 +48,7 @@ export default class ImportHandler {
|
||||
});
|
||||
userStates.delete(chatId);
|
||||
} catch (error) {
|
||||
console.error('Error importing products:', error);
|
||||
logger.error({ err: error }, 'Error importing products');
|
||||
await bot.sendMessage(chatId, 'Error importing products. Please check the data and try again.');
|
||||
await db.runAsync('ROLLBACK');
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import db from '../../../config/database.js';
|
||||
import { isAdmin } from '../../../middleware/auth.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class ListHandler {
|
||||
|
||||
@@ -62,7 +63,7 @@ export default class ListHandler {
|
||||
markup: keyboard
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in viewProductsPage:', error);
|
||||
logger.error({ err: error }, 'Error in viewProductsPage');
|
||||
return { text: 'Error loading products. Please try again.' };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { isAdmin } from '../../../middleware/auth.js';
|
||||
import LocationService from '../../../services/locationService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class NavigationHandler {
|
||||
|
||||
@@ -43,7 +44,7 @@ export default class NavigationHandler {
|
||||
{reply_markup: keyboard}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleProductManagement:', error);
|
||||
logger.error({ err: error }, 'Error in handleProductManagement');
|
||||
await bot.sendMessage(chatId, 'Error loading locations. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -79,7 +80,7 @@ export default class NavigationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleCountrySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleCountrySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading cities. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import bot from '../../../context/bot.js';
|
||||
import userStates from '../../../context/userStates.js';
|
||||
import LocationService from '../../../services/locationService.js';
|
||||
import ProductService from '../../../services/productService.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class ViewHandler {
|
||||
|
||||
@@ -82,7 +83,7 @@ export default class ViewHandler {
|
||||
await bot.deleteMessage(chatId, messageId);
|
||||
await bot.sendMessage(chatId, message, {reply_markup: keyboard});
|
||||
} catch (error) {
|
||||
console.error('Error in handleViewProduct:', error);
|
||||
logger.error({ err: error }, 'Error in handleViewProduct');
|
||||
await bot.sendMessage(chatId, 'Error loading product details. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import db from '../../config/database.js';
|
||||
import bot from "../../context/bot.js";
|
||||
import UserService from "../../services/userService.js";
|
||||
import userStates from "../../context/userStates.js";
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class UserDeletionHandler {
|
||||
static async handleDeleteAccount(callbackQuery) {
|
||||
@@ -29,7 +30,7 @@ export default class UserDeletionHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDeleteUser:', error);
|
||||
logger.error({ err: error }, 'Error in handleDeleteUser');
|
||||
await bot.sendMessage(chatId, 'Error processing delete request. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -46,7 +47,7 @@ export default class UserDeletionHandler {
|
||||
{ chat_id: chatId, message_id: callbackQuery.message.message_id, }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleConfirmDelete:', error);
|
||||
logger.error({ err: error }, 'Error in handleConfirmDelete');
|
||||
await bot.sendMessage(chatId, 'Error deleting user. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import config from "../../config/config.js";
|
||||
import bot from "../../context/bot.js";
|
||||
import UserService from "../../services/userService.js";
|
||||
import WalletService from "../../services/walletService.js";
|
||||
import logger from "../../utils/logger.js";
|
||||
|
||||
export default class UserHandler {
|
||||
static async canUseBot(msg) {
|
||||
@@ -83,7 +84,7 @@ export default class UserHandler {
|
||||
reply_markup: keyboard
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in showProfile:', error);
|
||||
logger.error({ err: error }, 'Error in showProfile');
|
||||
await bot.sendMessage(chatId, 'Error loading profile. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -116,7 +117,7 @@ export default class UserHandler {
|
||||
keyboard
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleStart:', error);
|
||||
logger.error({ err: error }, 'Error in handleStart');
|
||||
await bot.sendMessage(chatId, 'Error creating user profile. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import db from '../../config/database.js';
|
||||
import LocationService from "../../services/locationService.js";
|
||||
import bot from "../../context/bot.js";
|
||||
import UserService from "../../services/userService.js";
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class UserLocationHandler {
|
||||
static async handleSetLocation(callbackQuery) {
|
||||
@@ -46,7 +47,7 @@ export default class UserLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSetLocation:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetLocation');
|
||||
await bot.sendMessage(chatId, 'Error loading countries. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -78,7 +79,7 @@ export default class UserLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSetCountry:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetCountry');
|
||||
await bot.sendMessage(chatId, 'Error loading cities. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -110,7 +111,7 @@ export default class UserLocationHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSetCity:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetCity');
|
||||
await bot.sendMessage(chatId, 'Error loading districts. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -140,7 +141,7 @@ export default class UserLocationHandler {
|
||||
);
|
||||
} catch (error) {
|
||||
await db.runAsync('ROLLBACK');
|
||||
console.error('Error in handleSetDistrict:', error);
|
||||
logger.error({ err: error }, 'Error in handleSetDistrict');
|
||||
await bot.sendMessage(chatId, 'Error updating location. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import CategoryService from "../../services/categoryService.js";
|
||||
import UserService from "../../services/userService.js";
|
||||
import PurchaseService from "../../services/purchaseService.js";
|
||||
import Validators from '../../utils/validators.js';
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class UserProductHandler {
|
||||
static async showProducts(msg) {
|
||||
@@ -51,7 +52,7 @@ export default class UserProductHandler {
|
||||
await bot.sendMessage(chatId, message, {reply_markup: keyboard});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in showProducts:', error);
|
||||
logger.error({ err: error }, 'Error in showProducts');
|
||||
await bot.sendMessage(chatId, 'Error loading products. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -83,7 +84,7 @@ export default class UserProductHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleCountrySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleCountrySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading cities. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -115,7 +116,7 @@ export default class UserProductHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleCitySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleCitySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading districts. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -173,7 +174,7 @@ export default class UserProductHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDistrictSelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleDistrictSelection');
|
||||
await bot.sendMessage(chatId, 'Error loading categories. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -195,7 +196,7 @@ export default class UserProductHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, state.photoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +250,7 @@ export default class UserProductHandler {
|
||||
location: state?.location // Сохраняем информацию о локации
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleCategorySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleCategorySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading products. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -265,7 +266,7 @@ export default class UserProductHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, photoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +311,7 @@ export default class UserProductHandler {
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in handleSubcategorySelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleSubcategorySelection');
|
||||
await bot.sendMessage(chatId, 'Error loading products. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -338,7 +339,7 @@ export default class UserProductHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, state.photoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +399,7 @@ export default class UserProductHandler {
|
||||
location: state?.location // Сохраняем информацию о локации
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleProductSelection:', error);
|
||||
logger.error({ err: error }, 'Error in handleProductSelection');
|
||||
await bot.sendMessage(chatId, 'Error loading product details. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -458,7 +459,7 @@ export default class UserProductHandler {
|
||||
|
||||
await bot.answerCallbackQuery(callbackQuery.id);
|
||||
} catch (error) {
|
||||
console.error('Error in handleIncreaseQuantity:', error);
|
||||
logger.error({ err: error }, 'Error in handleIncreaseQuantity');
|
||||
await bot.answerCallbackQuery(callbackQuery.id);
|
||||
}
|
||||
}
|
||||
@@ -518,7 +519,7 @@ export default class UserProductHandler {
|
||||
|
||||
await bot.answerCallbackQuery(callbackQuery.id);
|
||||
} catch (error) {
|
||||
console.error('Error in handleDecreaseQuantity:', error);
|
||||
logger.error({ err: error }, 'Error in handleDecreaseQuantity');
|
||||
await bot.answerCallbackQuery(callbackQuery.id);
|
||||
}
|
||||
}
|
||||
@@ -627,7 +628,7 @@ export default class UserProductHandler {
|
||||
purchaseMessageId: purchaseMessage.message_id
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleBuyProduct:', error);
|
||||
logger.error({ err: error }, 'Error in handleBuyProduct');
|
||||
await bot.sendMessage(chatId, 'Error processing purchase. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -698,7 +699,7 @@ export default class UserProductHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, state.photoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting Public Photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting Public Photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,7 +744,7 @@ export default class UserProductHandler {
|
||||
hiddenPhotoMessageId: hiddenPhotoMessage ? hiddenPhotoMessage.message_id : null
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handlePay:', error);
|
||||
logger.error({ err: error }, 'Error in handlePay');
|
||||
await bot.sendMessage(chatId, 'Error processing purchase. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import CategoryService from "../../services/categoryService.js";
|
||||
import bot from "../../context/bot.js";
|
||||
import userStates from "../../context/userStates.js";
|
||||
import Validators from '../../utils/validators.js';
|
||||
import logger from '../../utils/logger.js';
|
||||
|
||||
export default class UserPurchaseHandler {
|
||||
static async viewPurchasePage(userId, page) {
|
||||
@@ -75,7 +76,7 @@ export default class UserPurchaseHandler {
|
||||
markup: keyboard
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in viewPurchasePage:', error);
|
||||
logger.error({ err: error }, 'Error in viewPurchasePage');
|
||||
return { text: 'Error loading purchase history. Please try again.' };
|
||||
}
|
||||
}
|
||||
@@ -99,7 +100,7 @@ export default class UserPurchaseHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, state.hiddenPhotoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting Hidden Photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting Hidden Photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ export default class UserPurchaseHandler {
|
||||
// Удаляем состояние пользователя
|
||||
userStates.delete(chatId);
|
||||
} catch (e) {
|
||||
console.error('Error in handlePurchaseListPage:', e);
|
||||
logger.error({ err: e }, 'Error in handlePurchaseListPage');
|
||||
await bot.sendMessage(chatId, 'Error loading purchase history. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -136,7 +137,7 @@ export default class UserPurchaseHandler {
|
||||
|
||||
await bot.sendMessage(chatId, text, { reply_markup: markup, parse_mode: 'Markdown' });
|
||||
} catch (error) {
|
||||
console.error('Error in showPurchases:', error);
|
||||
logger.error({ err: error }, 'Error in showPurchases');
|
||||
await bot.sendMessage(chatId, 'Error loading purchase history. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -172,7 +173,7 @@ export default class UserPurchaseHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, state.hiddenPhotoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting Hidden Photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting Hidden Photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ export default class UserPurchaseHandler {
|
||||
hiddenPhotoMessageId: hiddenPhotoMessage ? hiddenPhotoMessage.message_id : null
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in viewPurchase:', error);
|
||||
logger.error({ err: error }, 'Error in viewPurchase');
|
||||
await bot.sendMessage(chatId, 'Error loading purchase details. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -283,7 +284,7 @@ export default class UserPurchaseHandler {
|
||||
try {
|
||||
await bot.deleteMessage(chatId, state.hiddenPhotoMessageId);
|
||||
} catch (error) {
|
||||
console.error('Error deleting Hidden Photo message:', error);
|
||||
logger.error({ err: error }, 'Error deleting Hidden Photo message');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +294,7 @@ export default class UserPurchaseHandler {
|
||||
// Открываем список покупок для пользователя
|
||||
await this.showPurchases({ chat: { id: chatId }, from: { id: callbackQuery.from.id } });
|
||||
} catch (error) {
|
||||
console.error('Error in handleConfirmReceived:', error);
|
||||
logger.error({ err: error }, 'Error in handleConfirmReceived');
|
||||
await bot.sendMessage(chatId, 'Error confirming receipt. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import db from '../../../config/database.js';
|
||||
import WalletUtils from '../../../utils/walletUtils.js';
|
||||
import UserService from '../../../services/userService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class ArchiveHandler {
|
||||
static async handleViewArchivedWallets(callbackQuery) {
|
||||
@@ -80,7 +81,7 @@ export default class ArchiveHandler {
|
||||
reply_markup: { inline_keyboard: [[{ text: '« Back', callback_data: 'back_to_balance' }]] }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleViewArchivedWallets:', error);
|
||||
logger.error({ err: error }, 'Error in handleViewArchivedWallets');
|
||||
await bot.sendMessage(chatId, 'Error loading archived wallets. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import WalletUtils from '../../../utils/walletUtils.js';
|
||||
import UserService from '../../../services/userService.js';
|
||||
import WalletService from '../../../services/walletService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class BalanceHandler {
|
||||
static async showBalance(msg) {
|
||||
@@ -82,7 +83,7 @@ export default class BalanceHandler {
|
||||
|
||||
await bot.sendMessage(chatId, message, { reply_markup: keyboard, parse_mode: 'Markdown' });
|
||||
} catch (error) {
|
||||
console.error('Error in showBalance:', error);
|
||||
logger.error({ err: error }, 'Error in showBalance');
|
||||
await bot.sendMessage(chatId, 'Error loading balance. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import WalletService from '../../../services/walletService.js';
|
||||
import Validators from '../../../utils/validators.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import UserService from '../../../services/userService.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class CreateHandler {
|
||||
static async handleAddWallet(callbackQuery) {
|
||||
@@ -85,7 +86,7 @@ export default class CreateHandler {
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error generating wallet:', error);
|
||||
logger.error({ err: error }, 'Error generating wallet');
|
||||
await bot.editMessageText('❌ Error generating wallet. Please try again.', {
|
||||
chat_id: chatId, message_id: callbackQuery.message.message_id,
|
||||
reply_markup: { inline_keyboard: [[{ text: '« Back to Balance', callback_data: 'back_to_balance' }]] }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import db from '../../../config/database.js';
|
||||
import UserService from '../../../services/userService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class HistoryHandler {
|
||||
static async handleTransactionHistory(callbackQuery, page = 0) {
|
||||
@@ -61,7 +62,7 @@ export default class HistoryHandler {
|
||||
parse_mode: 'Markdown', reply_markup: keyboard
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleTransactionHistory:', error);
|
||||
logger.error({ err: error }, 'Error in handleTransactionHistory');
|
||||
await bot.sendMessage(chatId, 'Error loading transaction history. Please try again.');
|
||||
}
|
||||
}
|
||||
@@ -101,7 +102,7 @@ export default class HistoryHandler {
|
||||
reply_markup: { inline_keyboard: [[{ text: '« Back', callback_data: 'back_to_balance' }]] }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleWalletHistory:', error);
|
||||
logger.error({ err: error }, 'Error in handleWalletHistory');
|
||||
await bot.sendMessage(chatId, 'Error loading transaction history. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import db from '../../../config/database.js';
|
||||
import WalletUtils from '../../../utils/walletUtils.js';
|
||||
import UserService from '../../../services/userService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class RefreshHandler {
|
||||
static async handleRefreshBalance(callbackQuery) {
|
||||
@@ -66,7 +67,7 @@ export default class RefreshHandler {
|
||||
|
||||
await bot.deleteMessage(chatId, messageId);
|
||||
} catch (error) {
|
||||
console.error('Error in handleRefreshBalance:', error);
|
||||
logger.error({ err: error }, 'Error in handleRefreshBalance');
|
||||
await bot.answerCallbackQuery(callbackQuery.id, { text: '❌ Error refreshing balances.' });
|
||||
await bot.sendMessage(chatId, '❌ Error refreshing balances. Please try again.', {
|
||||
reply_markup: { inline_keyboard: [[{ text: '« Back', callback_data: 'back_to_balance' }]] }
|
||||
|
||||
@@ -2,6 +2,7 @@ import db from '../../../config/database.js';
|
||||
import WalletUtils from '../../../utils/walletUtils.js';
|
||||
import UserService from '../../../services/userService.js';
|
||||
import bot from '../../../context/bot.js';
|
||||
import logger from '../../../utils/logger.js';
|
||||
|
||||
export default class TopUpHandler {
|
||||
static async handleTopUpWallet(callbackQuery) {
|
||||
@@ -54,7 +55,7 @@ export default class TopUpHandler {
|
||||
reply_markup: { inline_keyboard: [[{ text: '« Back', callback_data: 'back_to_balance' }]] }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in handleTopUpWallet:', error);
|
||||
logger.error({ err: error }, 'Error in handleTopUpWallet');
|
||||
await bot.sendMessage(chatId, 'Error loading wallets. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { runMigrations, cleanUpInvalidForeignKeys } from './migrations/runner.js
|
||||
import './router/routes.js';
|
||||
import bot from './context/bot.js';
|
||||
import ErrorHandler from './utils/errorHandler.js';
|
||||
import logger from './utils/logger.js';
|
||||
import userHandler from './handlers/userHandlers/userHandler.js';
|
||||
import adminHandler from './handlers/adminHandlers/adminHandler.js';
|
||||
import callbackRouter from './router/callbackRouter.js';
|
||||
@@ -11,8 +12,7 @@ await runMigrations();
|
||||
await cleanUpInvalidForeignKeys();
|
||||
|
||||
const logDebug = (action, functionName) => {
|
||||
console.log(`[DEBUG] Button Press: ${action}`);
|
||||
console.log(`[DEBUG] Calling Function: ${functionName}`);
|
||||
logger.debug({ action, functionName }, 'Button Press');
|
||||
};
|
||||
|
||||
bot.onText(/\/start/, async (msg) => {
|
||||
@@ -63,7 +63,7 @@ bot.on('callback_query', async (callbackQuery) => {
|
||||
bot.on('polling_error', ErrorHandler.handlePollingError);
|
||||
|
||||
process.on('unhandledRejection', (error) => {
|
||||
console.error('Unhandled promise rejection:', error);
|
||||
logger.error({ err: error }, 'Unhandled promise rejection');
|
||||
});
|
||||
|
||||
console.log('Bot is running...');
|
||||
logger.info('Bot is running...');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
export default async function migration001(db) {
|
||||
await db.runAsync('BEGIN TRANSACTION');
|
||||
|
||||
@@ -88,5 +90,5 @@ export default async function migration001(db) {
|
||||
)`);
|
||||
|
||||
await db.runAsync('COMMIT');
|
||||
console.log('Migration 001: Initial schema created');
|
||||
logger.info('Migration 001: Initial schema created');
|
||||
}
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
export default async function migration002(db, checkColumnExists) {
|
||||
const balanceExists = await checkColumnExists('crypto_wallets', 'balance');
|
||||
if (!balanceExists) {
|
||||
await db.runAsync(`ALTER TABLE crypto_wallets ADD COLUMN balance REAL DEFAULT 0`);
|
||||
console.log('Migration 002: Column balance added to crypto_wallets');
|
||||
logger.info('Migration 002: Column balance added to crypto_wallets');
|
||||
}
|
||||
|
||||
const userIdExists = await checkColumnExists('transactions', 'user_id');
|
||||
if (!userIdExists) {
|
||||
await db.runAsync(`ALTER TABLE transactions ADD COLUMN user_id INTEGER NOT NULL`);
|
||||
console.log('Migration 002: Column user_id added to transactions');
|
||||
logger.info('Migration 002: Column user_id added to transactions');
|
||||
}
|
||||
|
||||
const walletTypeExists = await checkColumnExists('transactions', 'wallet_type');
|
||||
if (!walletTypeExists) {
|
||||
await db.runAsync(`ALTER TABLE transactions ADD COLUMN wallet_type TEXT NOT NULL`);
|
||||
console.log('Migration 002: Column wallet_type added to transactions');
|
||||
logger.info('Migration 002: Column wallet_type added to transactions');
|
||||
}
|
||||
|
||||
const txHashExists = await checkColumnExists('transactions', 'tx_hash');
|
||||
if (!txHashExists) {
|
||||
await db.runAsync(`ALTER TABLE transactions ADD COLUMN tx_hash TEXT NOT NULL`);
|
||||
console.log('Migration 002: Column tx_hash added to transactions');
|
||||
logger.info('Migration 002: Column tx_hash added to transactions');
|
||||
}
|
||||
|
||||
const statusExists = await checkColumnExists('purchases', 'status');
|
||||
if (!statusExists) {
|
||||
await db.runAsync(`ALTER TABLE purchases ADD COLUMN status TEXT DEFAULT 'pending'`);
|
||||
console.log('Migration 002: Column status added to purchases');
|
||||
logger.info('Migration 002: Column status added to purchases');
|
||||
}
|
||||
|
||||
console.log('Migration 002: Column additions complete');
|
||||
logger.info('Migration 002: Column additions complete');
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
export default async function migration003(db) {
|
||||
await db.runAsync(`CREATE INDEX IF NOT EXISTS idx_users_telegram_id ON users(telegram_id)`);
|
||||
await db.runAsync(`CREATE INDEX IF NOT EXISTS idx_crypto_wallets_user_type ON crypto_wallets(user_id, wallet_type)`);
|
||||
@@ -5,5 +7,5 @@ export default async function migration003(db) {
|
||||
await db.runAsync(`CREATE INDEX IF NOT EXISTS idx_purchases_user_product ON purchases(user_id, product_id)`);
|
||||
await db.runAsync(`CREATE INDEX IF NOT EXISTS idx_purchases_status ON purchases(status)`);
|
||||
await db.runAsync(`CREATE INDEX IF NOT EXISTS idx_products_location_category ON products(location_id, category_id)`);
|
||||
console.log('Migration 003: Indexes created');
|
||||
logger.info('Migration 003: Indexes created');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import db from '../config/database.js';
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
const ALLOWED_TABLES = new Set([
|
||||
'users', 'crypto_wallets', 'transactions', 'products',
|
||||
@@ -13,7 +14,7 @@ export const checkColumnExists = async (tableName, columnName) => {
|
||||
const result = await db.allAsync(`PRAGMA table_info(${tableName})`);
|
||||
return result.some(column => column.name === columnName);
|
||||
} catch (error) {
|
||||
console.error(`Error checking column ${columnName} in table ${tableName}:`, error);
|
||||
logger.error({ err: error, tableName, columnName }, 'Error checking column');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -21,9 +22,9 @@ export const checkColumnExists = async (tableName, columnName) => {
|
||||
export const cleanUpInvalidForeignKeys = async () => {
|
||||
try {
|
||||
await db.runAsync(`DELETE FROM crypto_wallets WHERE user_id NOT IN (SELECT id FROM users)`);
|
||||
console.log('Cleaned up invalid foreign key references in crypto_wallets table');
|
||||
logger.info('Cleaned up invalid foreign key references in crypto_wallets table');
|
||||
} catch (error) {
|
||||
console.error('Error cleaning up invalid foreign key references:', error);
|
||||
logger.error({ err: error }, 'Error cleaning up invalid foreign key references');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,7 +41,7 @@ export async function runMigrations() {
|
||||
];
|
||||
|
||||
for (let i = currentVersion; i < migrations.length; i++) {
|
||||
console.log(`Running migration ${i + 1}/${migrations.length}...`);
|
||||
logger.info({ migration: i + 1, total: migrations.length }, 'Running migration');
|
||||
if (i === 1) {
|
||||
await migrations[i](db, checkColumnExists);
|
||||
} else {
|
||||
@@ -52,5 +53,5 @@ export async function runMigrations() {
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`Migrations complete. Schema version: ${migrations.length}`);
|
||||
logger.info({ schemaVersion: migrations.length }, 'Migrations complete');
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
class CallbackRouter {
|
||||
constructor() {
|
||||
this.exactRoutes = new Map();
|
||||
@@ -29,7 +31,7 @@ class CallbackRouter {
|
||||
}
|
||||
}
|
||||
|
||||
console.warn(`No handler for callback: ${action}`);
|
||||
logger.warn({ action }, 'No handler for callback');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import callbackRouter from './callbackRouter.js';
|
||||
import messageRouter from './messageRouter.js';
|
||||
import { isAdmin } from '../middleware/auth.js';
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
import userHandler from '../handlers/userHandlers/userHandler.js';
|
||||
import userPurchaseHandler from '../handlers/userHandlers/userPurchaseHandler.js';
|
||||
@@ -17,8 +18,7 @@ import adminWalletsHandler from '../handlers/adminHandlers/adminWalletsHandler.j
|
||||
import adminUserHandler from '../handlers/adminHandlers/adminUserHandler.js';
|
||||
|
||||
const logDebug = (action, functionName) => {
|
||||
console.log(`[DEBUG] Button Press: ${action}`);
|
||||
console.log(`[DEBUG] Calling Function: ${functionName}`);
|
||||
logger.debug({ action, functionName }, 'Button Press');
|
||||
};
|
||||
|
||||
export function registerRoutes() {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import db from "../config/database.js";
|
||||
import logger from "../utils/logger.js";
|
||||
|
||||
class CategoryService {
|
||||
static async getCategoriesByLocationId(locationId) {
|
||||
@@ -9,7 +10,7 @@ class CategoryService {
|
||||
);
|
||||
return categories;
|
||||
} catch (error) {
|
||||
console.error('Error fetching categories by location ID:', error);
|
||||
logger.error({ err: error }, 'Error fetching categories by location ID');
|
||||
throw new Error('Failed to fetch categories');
|
||||
}
|
||||
}
|
||||
@@ -29,7 +30,7 @@ class CategoryService {
|
||||
);
|
||||
return category;
|
||||
} catch (error) {
|
||||
console.error('Error fetching category by ID:', error);
|
||||
logger.error({ err: error }, 'Error fetching category by ID');
|
||||
throw new Error('Failed to fetch category');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import db from "../config/database.js";
|
||||
import logger from "../utils/logger.js";
|
||||
|
||||
class LocationService {
|
||||
static async getCountries() {
|
||||
@@ -27,7 +28,7 @@ class LocationService {
|
||||
);
|
||||
return location;
|
||||
} catch (error) {
|
||||
console.error('Error fetching location:', error);
|
||||
logger.error({ err: error }, 'Error fetching location');
|
||||
throw new Error('Failed to fetch location');
|
||||
}
|
||||
}
|
||||
@@ -40,7 +41,7 @@ class LocationService {
|
||||
);
|
||||
return location;
|
||||
} catch (error) {
|
||||
console.error('Error fetching location by ID:', error);
|
||||
logger.error({ err: error }, 'Error fetching location by ID');
|
||||
throw new Error('Failed to fetch location');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import db from "../config/database.js";
|
||||
import Validators from "../utils/validators.js";
|
||||
import logger from "../utils/logger.js";
|
||||
|
||||
class ProductService {
|
||||
static async getProductById(productId) {
|
||||
@@ -11,7 +12,7 @@ class ProductService {
|
||||
try {
|
||||
return await db.getAsync(`SELECT * FROM products WHERE id = ?`, [productId]);
|
||||
} catch (error) {
|
||||
console.error('Error get product:', error);
|
||||
logger.error({ err: error }, 'Error get product');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +71,7 @@ class ProductService {
|
||||
[quantity, productId]
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error decreasing product quantity:', error);
|
||||
logger.error({ err: error }, 'Error decreasing product quantity');
|
||||
throw new Error('Failed to update product quantity');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import db from "../config/database.js";
|
||||
import crypto from "crypto";
|
||||
import logger from "../utils/logger.js";
|
||||
|
||||
class PurchaseService {
|
||||
static async getPurchasesByUserId(userId, limit, offset) {
|
||||
@@ -24,7 +25,7 @@ class PurchaseService {
|
||||
`, [userId, limit, offset]);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error get purchases:', error);
|
||||
logger.error({ err: error }, 'Error get purchases');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +37,7 @@ class PurchaseService {
|
||||
[purchaseId]
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error getting purchase by ID:', error);
|
||||
logger.error({ err: error }, 'Error getting purchase by ID');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +114,7 @@ class PurchaseService {
|
||||
return result.lastID;
|
||||
} catch (error) {
|
||||
try { await db.runAsync('ROLLBACK'); } catch (_) {}
|
||||
console.error('Error creating purchase:', error);
|
||||
logger.error({ err: error }, 'Error creating purchase');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +153,7 @@ class PurchaseService {
|
||||
await db.runAsync('COMMIT');
|
||||
} catch (error) {
|
||||
try { await db.runAsync('ROLLBACK'); } catch (_) {}
|
||||
console.error('Error updating purchase status:', error);
|
||||
logger.error({ err: error }, 'Error updating purchase status');
|
||||
throw new Error('Failed to update purchase status');
|
||||
}
|
||||
}
|
||||
@@ -165,7 +166,7 @@ class PurchaseService {
|
||||
);
|
||||
return total.total;
|
||||
} catch (error) {
|
||||
console.error('Error fetching total purchases by user ID:', error);
|
||||
logger.error({ err: error }, 'Error fetching total purchases by user ID');
|
||||
throw new Error('Failed to fetch total purchases');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import db from "../config/database.js";
|
||||
import Wallet from "../models/Wallet.js";
|
||||
import WalletUtils from "../utils/walletUtils.js";
|
||||
import logger from "../utils/logger.js";
|
||||
|
||||
const ALLOWED_USER_FIELDS = new Set([
|
||||
'telegram_id', 'username', 'country', 'city',
|
||||
@@ -35,7 +36,6 @@ class UserService {
|
||||
try {
|
||||
// Нормализуем и валидируем telegram_id
|
||||
const normalizedTelegramId = this.normalizeTelegramId(userData?.telegram_id);
|
||||
// console.log("Normalized telegram_id:", normalizedTelegramId); // Отладочный вывод
|
||||
this.validateTelegramId(normalizedTelegramId);
|
||||
|
||||
// Обновляем значение telegram_id в объекте userData
|
||||
@@ -44,7 +44,7 @@ class UserService {
|
||||
// Проверяем, существует ли пользователь с таким telegram_id
|
||||
const existingUser = await this.getUserByTelegramId(normalizedTelegramId);
|
||||
if (existingUser) {
|
||||
console.log("User already exists with telegram_id:", normalizedTelegramId);
|
||||
logger.info({ telegramId: normalizedTelegramId }, 'User already exists');
|
||||
return existingUser.id;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class UserService {
|
||||
return result.lastID;
|
||||
} catch (error) {
|
||||
await db.runAsync('ROLLBACK');
|
||||
console.error('Error creating user:', error);
|
||||
logger.error({ err: error }, 'Error creating user');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class UserService {
|
||||
[String(userId)]
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error getting user:', error);
|
||||
logger.error({ err: error }, 'Error getting user');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,7 @@ class UserService {
|
||||
[normalizedTelegramId]
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error getting user:', error);
|
||||
logger.error({ err: error }, 'Error getting user');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class UserService {
|
||||
GROUP BY u.id
|
||||
`, [normalizedTelegramId]);
|
||||
} catch (error) {
|
||||
console.error('Error getting user stats:', error);
|
||||
logger.error({ err: error }, 'Error getting user stats');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -169,9 +169,9 @@ class UserService {
|
||||
[remainingBalance, user.id]
|
||||
);
|
||||
|
||||
console.log(`[DEBUG] Updated total_balance for user ${user.id}: ${remainingBalance}`);
|
||||
logger.debug({ userId: user.id, remainingBalance }, 'Updated total_balance');
|
||||
} catch (error) {
|
||||
console.error('Error recalculating user balance:', error);
|
||||
logger.error({ err: error }, 'Error recalculating user balance');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ class UserService {
|
||||
await db.runAsync('COMMIT');
|
||||
} catch (e) {
|
||||
await db.runAsync("ROLLBACK");
|
||||
console.error('Error deleting user:', e);
|
||||
logger.error({ err: e }, 'Error deleting user');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -211,7 +211,7 @@ class UserService {
|
||||
// Возвращаем сумму доступного крипто-баланса и бонусного баланса
|
||||
return user.total_balance + user.bonus_balance;
|
||||
} catch (error) {
|
||||
console.error('Error getting user balance:', error);
|
||||
logger.error({ err: error }, 'Error getting user balance');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import config from "../config/config.js";
|
||||
import WalletUtils from "../utils/walletUtils.js";
|
||||
import WalletGenerator from "../utils/walletGenerator.js";
|
||||
import { encrypt, decrypt } from '../utils/encryption.js';
|
||||
import logger from '../utils/logger.js';
|
||||
|
||||
class WalletService {
|
||||
static async getArchivedWalletsCount(user) {
|
||||
@@ -17,7 +18,7 @@ class WalletService {
|
||||
);
|
||||
return archivedWallets.total;
|
||||
} catch (error) {
|
||||
console.error('Error fetching archived wallets count:', error);
|
||||
logger.error({ err: error }, 'Error fetching archived wallets count');
|
||||
throw new Error('Failed to fetch archived wallets count');
|
||||
}
|
||||
}
|
||||
@@ -41,7 +42,7 @@ class WalletService {
|
||||
|
||||
return totalBalance;
|
||||
} catch (error) {
|
||||
console.error('Error fetching active wallets balance:', error);
|
||||
logger.error({ err: error }, 'Error fetching active wallets balance');
|
||||
throw new Error('Failed to fetch active wallets balance');
|
||||
}
|
||||
}
|
||||
@@ -65,7 +66,7 @@ class WalletService {
|
||||
|
||||
return totalBalance;
|
||||
} catch (error) {
|
||||
console.error('Error fetching archived wallets balance:', error);
|
||||
logger.error({ err: error }, 'Error fetching archived wallets balance');
|
||||
throw new Error('Failed to fetch archived wallets balance');
|
||||
}
|
||||
}
|
||||
@@ -82,7 +83,7 @@ class WalletService {
|
||||
|
||||
return wallets;
|
||||
} catch (error) {
|
||||
console.error('Error fetching wallets by type:', error);
|
||||
logger.error({ err: error }, 'Error fetching wallets by type');
|
||||
throw new Error('Failed to fetch wallets by type');
|
||||
}
|
||||
}
|
||||
@@ -128,11 +129,7 @@ class WalletService {
|
||||
// Получаем адрес для базового типа
|
||||
const walletData = wallets[baseType.toUpperCase()];
|
||||
if (!walletData || !walletData.address) {
|
||||
console.error('Wallet generation failed:', {
|
||||
baseType,
|
||||
wallets: Object.keys(wallets),
|
||||
walletData
|
||||
});
|
||||
logger.error({ baseType, walletKeys: Object.keys(wallets) }, 'Wallet generation failed');
|
||||
throw new Error('Failed to generate wallet address');
|
||||
}
|
||||
const address = walletData.address;
|
||||
@@ -159,7 +156,7 @@ class WalletService {
|
||||
// Проверяем целостность записанной мнемоники
|
||||
const decryptedMnemonic = decrypt(insertedWallet.mnemonic, userId);
|
||||
if (decryptedMnemonic !== mnemonic) {
|
||||
console.error('Mnemonic verification failed for wallet:', walletType);
|
||||
logger.error({ walletType }, 'Mnemonic verification failed');
|
||||
await db.runAsync(
|
||||
`DELETE FROM crypto_wallets
|
||||
WHERE user_id = ? AND wallet_type = ?`,
|
||||
@@ -168,12 +165,7 @@ class WalletService {
|
||||
throw new Error('Mnemonic verification failed');
|
||||
}
|
||||
|
||||
console.log(`Successfully created and verified wallet: ${walletType}`, {
|
||||
address,
|
||||
derivationPath,
|
||||
userId,
|
||||
walletType
|
||||
});
|
||||
logger.info({ walletType, address, derivationPath, userId }, 'Successfully created and verified wallet');
|
||||
return {
|
||||
address,
|
||||
derivationPath,
|
||||
@@ -182,7 +174,7 @@ class WalletService {
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error creating wallet:', error);
|
||||
logger.error({ err: error }, 'Error creating wallet');
|
||||
throw new Error('Failed to create wallet: ' + error.message);
|
||||
}
|
||||
}
|
||||
@@ -194,7 +186,7 @@ class WalletService {
|
||||
}
|
||||
return decrypt(encryptedMnemonic, userId);
|
||||
} catch (error) {
|
||||
console.error('Error decrypting mnemonic:', error);
|
||||
logger.error({ err: error }, 'Error decrypting mnemonic');
|
||||
throw new Error('Failed to decrypt mnemonic: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import logger from './logger.js';
|
||||
|
||||
export default class ErrorHandler {
|
||||
static async handleError(bot, chatId, error, context) {
|
||||
console.error(`Error in ${context}:`, error);
|
||||
logger.error({ err: error, context }, 'Error in handler');
|
||||
|
||||
const errorMessage = process.env.NODE_ENV === 'development'
|
||||
? `Error: ${error.message}`
|
||||
@@ -9,16 +11,16 @@ export default class ErrorHandler {
|
||||
try {
|
||||
await bot.sendMessage(chatId, errorMessage);
|
||||
} catch (sendError) {
|
||||
console.error('Error sending error message:', sendError);
|
||||
logger.error({ err: sendError }, 'Error sending error message');
|
||||
}
|
||||
}
|
||||
|
||||
static handlePollingError(error) {
|
||||
if (error.code === 'ETELEGRAM') {
|
||||
console.error('Telegram API Error:', error.message);
|
||||
logger.error({ err: error }, 'Telegram API Error');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.error('Polling error:', error);
|
||||
logger.error({ err: error }, 'Polling error');
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/utils/logger.js
Normal file
19
src/utils/logger.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import pino from 'pino';
|
||||
|
||||
const level = process.env.LOG_LEVEL || 'info';
|
||||
|
||||
const options = {
|
||||
level,
|
||||
redact: ['*.mnemonic', '*.privateKey', '*.secret', '*.token', '*.password', '*.ENCRYPTION_KEY', '*.BOT_TOKEN'],
|
||||
serializers: {
|
||||
err: pino.stdSerializers.err,
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
options.transport = { target: 'pino-pretty', options: { colorize: true } };
|
||||
}
|
||||
|
||||
const logger = pino(options);
|
||||
|
||||
export default logger;
|
||||
@@ -8,6 +8,7 @@ import * as bitcoin from 'bitcoinjs-lib';
|
||||
import * as ecc from 'tiny-secp256k1';
|
||||
import { ECPairFactory } from 'ecpair';
|
||||
import CryptoJS from 'crypto';
|
||||
import logger from './logger.js';
|
||||
|
||||
const ECPair = ECPairFactory(ecc);
|
||||
|
||||
@@ -16,7 +17,7 @@ export default class WalletGenerator {
|
||||
try {
|
||||
return bip39.generateMnemonic(128); // 12 слов
|
||||
} catch (error) {
|
||||
console.error('Error generating mnemonic:', error);
|
||||
logger.error({ err: error }, 'Error generating mnemonic');
|
||||
throw new Error('Failed to generate mnemonic');
|
||||
}
|
||||
}
|
||||
@@ -86,7 +87,7 @@ export default class WalletGenerator {
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in generateWallets:', error);
|
||||
logger.error({ err: error }, 'Error in generateWallets');
|
||||
throw new Error('Failed to generate cryptocurrency wallets: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// walletUtils.js
|
||||
|
||||
import axios from 'axios';
|
||||
import db from '../config/database.js'; // Импортируем базу данных
|
||||
import db from '../config/database.js';
|
||||
import logger from './logger.js';
|
||||
|
||||
// Массив публичных RPC-узлов
|
||||
const rpcNodes = [
|
||||
@@ -94,14 +95,14 @@ export default class WalletUtils {
|
||||
static async getCryptoPrices() {
|
||||
// Если кеш актуален, возвращаем его
|
||||
if (cryptoPricesCache && Date.now() - cacheTimestamp < CACHE_TTL) {
|
||||
console.log('[DEBUG] Using cached crypto prices:', cryptoPricesCache);
|
||||
logger.debug('Using cached crypto prices');
|
||||
return cryptoPricesCache;
|
||||
}
|
||||
|
||||
// Если кеш устарел, запрашиваем новые данные
|
||||
for (const api of cryptoPriceAPIs) {
|
||||
try {
|
||||
console.log(`[DEBUG] Trying to fetch prices from ${api.name}...`);
|
||||
logger.debug({ apiName: api.name }, 'Trying to fetch prices');
|
||||
let data;
|
||||
if (api.name === 'Binance') {
|
||||
data = await api.parser(api.urls);
|
||||
@@ -109,7 +110,7 @@ export default class WalletUtils {
|
||||
const response = await axios.get(api.url);
|
||||
data = api.parser(response.data);
|
||||
}
|
||||
console.log(`[DEBUG] Successfully fetched prices from ${api.name}:`, data);
|
||||
logger.debug({ apiName: api.name }, 'Successfully fetched prices');
|
||||
|
||||
// Обновляем кеш
|
||||
cryptoPricesCache = data;
|
||||
@@ -118,17 +119,17 @@ export default class WalletUtils {
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 429) {
|
||||
console.log(`[DEBUG] Rate limit exceeded on ${api.name}. Retrying after 2 seconds...`);
|
||||
logger.debug({ apiName: api.name }, 'Rate limit exceeded, retrying after 2 seconds');
|
||||
await sleep(2000);
|
||||
continue; // Пробуем снова с тем же API
|
||||
} else {
|
||||
console.error(`[DEBUG] Error fetching prices from ${api.name}:`, error.message);
|
||||
logger.error({ err: error, apiName: api.name }, 'Error fetching prices');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Если все API не сработали, используем fallback-значения
|
||||
console.error('[DEBUG] All APIs failed. Using fallback prices.');
|
||||
logger.error('All APIs failed. Using fallback prices.');
|
||||
cryptoPricesCache = {
|
||||
btc: 0, ltc: 0, eth: 0, usdt: 1, usdc: 1
|
||||
};
|
||||
@@ -139,17 +140,17 @@ export default class WalletUtils {
|
||||
|
||||
async fetchApiRequest(url) {
|
||||
try {
|
||||
console.log(`[DEBUG] Fetching data from: ${url}`); // Логируем URL запроса
|
||||
logger.debug({ url }, 'Fetching data');
|
||||
const response = await axios.get(url);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error(`Error fetching data from ${url}:`, error);
|
||||
logger.error({ err: error, url }, 'Error fetching data');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchRpcRequest(method, params) {
|
||||
console.log(`[DEBUG] fetchRpcRequest called with method: ${method}, params: ${JSON.stringify(params)}`); // Логируем вызов метода
|
||||
logger.debug({ method, params }, 'fetchRpcRequest called');
|
||||
|
||||
const results = [];
|
||||
for (const node of rpcNodes) {
|
||||
@@ -163,12 +164,12 @@ export default class WalletUtils {
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
results.push(response.data.result);
|
||||
console.log(`Запрос успешно выполнен на узле ${node}`); // Логируем успешный запрос
|
||||
logger.debug({ node }, 'Request successful');
|
||||
} else {
|
||||
console.warn(`Некорректный ответ от узла ${node}`); // Логируем некорректный ответ
|
||||
logger.warn({ node }, 'Invalid response');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Ошибка на узле ${node}: ${error.message}`); // Логируем ошибку
|
||||
logger.error({ err: error, node }, 'Node error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,68 +179,68 @@ export default class WalletUtils {
|
||||
|
||||
const uniqueResults = [...new Set(results)];
|
||||
if (uniqueResults.length === 1) {
|
||||
console.log("Баланс совпадает на всех узлах:", uniqueResults[0]); // Логируем совпадение балансов
|
||||
logger.debug('Balance matches across all nodes');
|
||||
return uniqueResults[0];
|
||||
} else {
|
||||
console.warn("Результаты отличаются на некоторых узлах. Возвращаем первый результат."); // Логируем различия
|
||||
logger.warn('Results differ across nodes. Returning first result.');
|
||||
return results[0];
|
||||
}
|
||||
}
|
||||
|
||||
async getBtcBalance() {
|
||||
if (!this.btcAddress) {
|
||||
console.log('[DEBUG] BTC address is not provided, skipping balance check.'); // Логируем отсутствие адреса
|
||||
logger.debug('BTC address is not provided, skipping balance check');
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
const url = `https://blockchain.info/balance?active=${this.btcAddress}`;
|
||||
console.log(`[DEBUG] Fetching BTC balance from: ${url}`); // Логируем URL запроса
|
||||
logger.debug({ url }, 'Fetching BTC balance');
|
||||
const data = await this.fetchApiRequest(url);
|
||||
return data?.[this.btcAddress]?.final_balance / 100000000 || 0;
|
||||
} catch (error) {
|
||||
console.error('Error getting BTC balance:', error);
|
||||
logger.error({ err: error }, 'Error getting BTC balance');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async getLtcBalance() {
|
||||
if (!this.ltcAddress) {
|
||||
console.log('[DEBUG] LTC address is not provided, skipping balance check.'); // Логируем отсутствие адреса
|
||||
logger.debug('LTC address is not provided, skipping balance check');
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
const url = `https://api.blockcypher.com/v1/ltc/main/addrs/${this.ltcAddress}/balance`;
|
||||
console.log(`[DEBUG] Fetching LTC balance from: ${url}`); // Логируем URL запроса
|
||||
logger.debug({ url }, 'Fetching LTC balance');
|
||||
const data = await this.fetchApiRequest(url);
|
||||
return data?.balance / 100000000 || 0;
|
||||
} catch (error) {
|
||||
console.error('Error getting LTC balance:', error);
|
||||
logger.error({ err: error }, 'Error getting LTC balance');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async getEthBalance() {
|
||||
if (!this.ethAddress) {
|
||||
console.log('[DEBUG] ETH address is not provided, skipping balance check.'); // Логируем отсутствие адреса
|
||||
logger.debug('ETH address is not provided, skipping balance check');
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
console.log(`[DEBUG] Fetching ETH balance for address: ${this.ethAddress}`); // Логируем адрес
|
||||
logger.debug({ addressPrefix: this.ethAddress.slice(0, 6) + '...' }, 'Fetching ETH balance');
|
||||
const balanceHex = await this.fetchRpcRequest("eth_getBalance", [this.ethAddress, "latest"]);
|
||||
return parseInt(balanceHex, 16) / 1e18;
|
||||
} catch (error) {
|
||||
console.error('Error getting ETH balance:', error);
|
||||
logger.error({ err: error }, 'Error getting ETH balance');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async getUsdtErc20Balance() {
|
||||
if (!this.usdtAddress) {
|
||||
console.log('[DEBUG] USDT address is not provided, skipping balance check.'); // Логируем отсутствие адреса
|
||||
logger.debug('USDT address is not provided, skipping balance check');
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
console.log(`[DEBUG] Fetching USDT ERC-20 balance for address: ${this.usdtAddress}`); // Логируем адрес
|
||||
logger.debug({ addressPrefix: this.usdtAddress.slice(0, 6) + '...' }, 'Fetching USDT ERC-20 balance');
|
||||
const balanceHex = await this.fetchRpcRequest("eth_call", [
|
||||
{
|
||||
to: "0xdac17f958d2ee523a2206206994597c13d831ec7",
|
||||
@@ -249,18 +250,18 @@ export default class WalletUtils {
|
||||
]);
|
||||
return parseInt(balanceHex, 16) / 1e6;
|
||||
} catch (error) {
|
||||
console.error('Error getting USDT ERC-20 balance:', error);
|
||||
logger.error({ err: error }, 'Error getting USDT ERC-20 balance');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async getUsdcErc20Balance() {
|
||||
if (!this.usdcAddress) {
|
||||
console.log('[DEBUG] USDC address is not provided, skipping balance check.'); // Логируем отсутствие адреса
|
||||
logger.debug('USDC address is not provided, skipping balance check');
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
console.log(`[DEBUG] Fetching USDC ERC-20 balance for address: ${this.usdcAddress}`); // Логируем адрес
|
||||
logger.debug({ addressPrefix: this.usdcAddress.slice(0, 6) + '...' }, 'Fetching USDC ERC-20 balance');
|
||||
const balanceHex = await this.fetchRpcRequest("eth_call", [
|
||||
{
|
||||
to: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
||||
@@ -270,7 +271,7 @@ export default class WalletUtils {
|
||||
]);
|
||||
return parseInt(balanceHex, 16) / 1e6;
|
||||
} catch (error) {
|
||||
console.error('Error getting USDC ERC-20 balance:', error);
|
||||
logger.error({ err: error }, 'Error getting USDC ERC-20 balance');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -310,7 +311,7 @@ export default class WalletUtils {
|
||||
}
|
||||
|
||||
async getAllBalancesExt() {
|
||||
console.log('[DEBUG] getAllBalancesExt called'); // Логируем вызов метода
|
||||
logger.debug('getAllBalancesExt called');
|
||||
|
||||
const [
|
||||
btcBalance,
|
||||
@@ -328,14 +329,7 @@ export default class WalletUtils {
|
||||
WalletUtils.getCryptoPrices()
|
||||
]);
|
||||
|
||||
console.log('[DEBUG] Balances fetched:', { // Логируем полученные балансы
|
||||
btcBalance,
|
||||
ltcBalance,
|
||||
ethBalance,
|
||||
usdtErc20Balance,
|
||||
usdcErc20Balance,
|
||||
prices
|
||||
});
|
||||
logger.debug({ btcBalance, ltcBalance, ethBalance, usdtErc20Balance, usdcErc20Balance }, 'Balances fetched');
|
||||
|
||||
return {
|
||||
BTC: { amount: btcBalance, usdValue: btcBalance * prices.btc },
|
||||
|
||||
Reference in New Issue
Block a user