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:
NW
2026-06-22 01:42:47 +01:00
parent ba80784ae7
commit ce1b6003cb
49 changed files with 5624 additions and 6079 deletions

11197
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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 {

View File

@@ -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);
});
});

View File

@@ -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);
}
};

View File

@@ -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.',

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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, 'Ошибка обновления категории. Пожалуйста, попробуйте снова.');
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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');
}

View File

@@ -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.');
}
}

View File

@@ -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');
}

View File

@@ -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.' };
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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.');
}
}

View File

@@ -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' }]] }

View File

@@ -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.');
}
}

View File

@@ -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' }]] }

View File

@@ -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.');
}
}

View File

@@ -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...');

View File

@@ -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');
}

View File

@@ -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');
}

View File

@@ -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');
}

View File

@@ -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');
}

View File

@@ -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');
}
}

View File

@@ -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() {

View File

@@ -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');
}
}

View File

@@ -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');
}
}

View File

@@ -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');
}
}

View File

@@ -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');
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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
View 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;

View File

@@ -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);
}
}

View File

@@ -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 },