minor edits to aesthetics and functionality
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
// adminWalletsHandler.js
|
||||||
|
|
||||||
|
|
||||||
import bot from "../../context/bot.js";
|
import bot from "../../context/bot.js";
|
||||||
import config from '../../config/config.js';
|
import config from '../../config/config.js';
|
||||||
import WalletService from '../../services/walletService.js';
|
import WalletService from '../../services/walletService.js';
|
||||||
@@ -28,8 +31,8 @@ export default class AdminWalletsHandler {
|
|||||||
{ text: 'Litecoin (LTC)', callback_data: 'wallet_type_LTC' }
|
{ text: 'Litecoin (LTC)', callback_data: 'wallet_type_LTC' }
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ text: 'Tether (USDT)', callback_data: 'wallet_type_USDT' },
|
{ text: 'USDT ERC20', callback_data: 'wallet_type_USDT' },
|
||||||
{ text: 'USD Coin (USDC)', callback_data: 'wallet_type_USDC' },
|
{ text: 'USDC ERC20', callback_data: 'wallet_type_USDC' },
|
||||||
{ text: 'Ethereum (ETH)', callback_data: 'wallet_type_ETH' }
|
{ text: 'Ethereum (ETH)', callback_data: 'wallet_type_ETH' }
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@@ -73,24 +76,55 @@ export default class AdminWalletsHandler {
|
|||||||
const endIndex = startIndex + pageSize;
|
const endIndex = startIndex + pageSize;
|
||||||
const walletsPage = wallets.slice(startIndex, endIndex);
|
const walletsPage = wallets.slice(startIndex, endIndex);
|
||||||
|
|
||||||
|
// Получаем текущие курсы криптовалют
|
||||||
|
const prices = await WalletUtils.getCryptoPrices();
|
||||||
|
|
||||||
// Формируем список кошельков с балансами
|
// Формируем список кошельков с балансами
|
||||||
let walletList = '';
|
let walletList = '';
|
||||||
for (const wallet of walletsPage) {
|
for (const wallet of walletsPage) {
|
||||||
const walletUtilsInstance = new WalletUtils(
|
// Определяем базовый тип кошелька (например, USDT_1735846098129 -> USDT)
|
||||||
wallet.wallet_type === 'BTC' ? wallet.address : null,
|
|
||||||
wallet.wallet_type === 'LTC' ? wallet.address : null,
|
|
||||||
wallet.wallet_type === 'ETH' || wallet.wallet_type === 'USDT' || wallet.wallet_type === 'USDC' ? wallet.address : null,
|
|
||||||
null, // userId не нужен для админки
|
|
||||||
Date.now() - 30 * 24 * 60 * 60 * 1000
|
|
||||||
);
|
|
||||||
|
|
||||||
const balances = await walletUtilsInstance.getAllBalances();
|
|
||||||
const baseType = WalletUtils.getBaseWalletType(wallet.wallet_type);
|
const baseType = WalletUtils.getBaseWalletType(wallet.wallet_type);
|
||||||
const balance = balances[baseType] || { amount: 0, usdValue: 0 };
|
|
||||||
|
|
||||||
walletList += `💰 *${wallet.wallet_type}*\n`;
|
// Определяем, является ли кошелек архивным
|
||||||
walletList += `├ Balance: ${balance.amount.toFixed(8)} ${wallet.wallet_type}\n`;
|
const isArchived = wallet.wallet_type.includes('_');
|
||||||
walletList += `├ Value: $${balance.usdValue.toFixed(2)}\n`;
|
|
||||||
|
// Форматируем дату архивации (если кошелек архивный)
|
||||||
|
let archivedDate = '';
|
||||||
|
if (isArchived) {
|
||||||
|
const timestamp = wallet.wallet_type.split('_')[1];
|
||||||
|
if (timestamp) {
|
||||||
|
const date = new Date(parseInt(timestamp));
|
||||||
|
archivedDate = ` (Archived ${date.toLocaleString()})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем баланс из поля balance
|
||||||
|
const balance = wallet.balance || 0;
|
||||||
|
|
||||||
|
// Рассчитываем значение в долларах
|
||||||
|
let usdValue = 0;
|
||||||
|
switch (baseType) {
|
||||||
|
case 'BTC':
|
||||||
|
usdValue = balance * prices.btc;
|
||||||
|
break;
|
||||||
|
case 'LTC':
|
||||||
|
usdValue = balance * prices.ltc;
|
||||||
|
break;
|
||||||
|
case 'ETH':
|
||||||
|
usdValue = balance * prices.eth;
|
||||||
|
break;
|
||||||
|
case 'USDT':
|
||||||
|
usdValue = balance; // USDT привязан к доллару
|
||||||
|
break;
|
||||||
|
case 'USDC':
|
||||||
|
usdValue = balance; // USDC привязан к доллару
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Формируем строку для кошелька
|
||||||
|
walletList += `💰 ${baseType}${archivedDate}\n`;
|
||||||
|
walletList += `├ Balance: ${balance.toFixed(8)} ${baseType}\n`;
|
||||||
|
walletList += `├ Value: $${usdValue.toFixed(2)}\n`;
|
||||||
walletList += `└ Address: \`${wallet.address}\`\n\n`;
|
walletList += `└ Address: \`${wallet.address}\`\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,20 +165,38 @@ export default class AdminWalletsHandler {
|
|||||||
|
|
||||||
static async calculateTotalBalance(wallets) {
|
static async calculateTotalBalance(wallets) {
|
||||||
let totalBalance = 0;
|
let totalBalance = 0;
|
||||||
|
|
||||||
for (const wallet of wallets) {
|
|
||||||
const walletUtilsInstance = new WalletUtils(
|
|
||||||
wallet.wallet_type === 'BTC' ? wallet.address : null,
|
|
||||||
wallet.wallet_type === 'LTC' ? wallet.address : null,
|
|
||||||
wallet.wallet_type === 'ETH' || wallet.wallet_type === 'USDT' || wallet.wallet_type === 'USDC' ? wallet.address : null,
|
|
||||||
null, // userId не нужен для админки
|
|
||||||
Date.now() - 30 * 24 * 60 * 60 * 1000
|
|
||||||
);
|
|
||||||
|
|
||||||
const balances = await walletUtilsInstance.getAllBalances();
|
// Получаем текущие курсы криптовалют
|
||||||
|
const prices = await WalletUtils.getCryptoPrices();
|
||||||
|
|
||||||
|
for (const wallet of wallets) {
|
||||||
|
// Определяем базовый тип кошелька (например, USDT_1735846098129 -> USDT)
|
||||||
const baseType = WalletUtils.getBaseWalletType(wallet.wallet_type);
|
const baseType = WalletUtils.getBaseWalletType(wallet.wallet_type);
|
||||||
const balance = balances[baseType] || { usdValue: 0 };
|
|
||||||
totalBalance += balance.usdValue;
|
// Получаем баланс из поля balance
|
||||||
|
const balance = wallet.balance || 0;
|
||||||
|
|
||||||
|
// Рассчитываем значение в долларах
|
||||||
|
let usdValue = 0;
|
||||||
|
switch (baseType) {
|
||||||
|
case 'BTC':
|
||||||
|
usdValue = balance * prices.btc;
|
||||||
|
break;
|
||||||
|
case 'LTC':
|
||||||
|
usdValue = balance * prices.ltc;
|
||||||
|
break;
|
||||||
|
case 'ETH':
|
||||||
|
usdValue = balance * prices.eth;
|
||||||
|
break;
|
||||||
|
case 'USDT':
|
||||||
|
usdValue = balance; // USDT привязан к доллару
|
||||||
|
break;
|
||||||
|
case 'USDC':
|
||||||
|
usdValue = balance; // USDC привязан к доллару
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalBalance += usdValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalBalance;
|
return totalBalance;
|
||||||
@@ -187,62 +239,86 @@ export default class AdminWalletsHandler {
|
|||||||
const action = callbackQuery.data;
|
const action = callbackQuery.data;
|
||||||
const chatId = callbackQuery.message.chat.id;
|
const chatId = callbackQuery.message.chat.id;
|
||||||
const walletType = action.split('_').pop();
|
const walletType = action.split('_').pop();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Удаляем предыдущее сообщение перед отправкой нового
|
// Удаляем предыдущее сообщение перед отправкой нового
|
||||||
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
|
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
|
||||||
|
|
||||||
// Получаем все кошельки выбранного типа
|
// Получаем все кошельки выбранного типа (активные и архивные)
|
||||||
const wallets = await WalletService.getWalletsByType(walletType);
|
const wallets = await WalletService.getWalletsByType(walletType);
|
||||||
|
|
||||||
if (wallets.length === 0) {
|
if (wallets.length === 0) {
|
||||||
await bot.sendMessage(chatId, `No wallets found for ${walletType}.`);
|
await bot.sendMessage(chatId, `No wallets found for ${walletType}.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Расшифровываем мнемоническую фразу и получаем балансы
|
// Получаем текущие курсы криптовалют
|
||||||
|
const prices = await WalletUtils.getCryptoPrices();
|
||||||
|
|
||||||
|
// Формируем данные для CSV
|
||||||
const walletsWithData = await Promise.all(wallets.map(async (wallet) => {
|
const walletsWithData = await Promise.all(wallets.map(async (wallet) => {
|
||||||
if (!wallet.mnemonic) {
|
// Определяем базовый тип кошелька (например, USDT1735846098129 -> USDT)
|
||||||
console.error(`Mnemonic is missing for wallet with ID ${wallet.id}`);
|
const baseType = WalletUtils.getBaseWalletType(wallet.wallet_type);
|
||||||
return null; // Пропускаем кошелек, если mnemonic отсутствует
|
|
||||||
|
// Получаем баланс из поля balance
|
||||||
|
const balance = wallet.balance || 0;
|
||||||
|
|
||||||
|
// Рассчитываем значение в долларах
|
||||||
|
let usdValue = 0;
|
||||||
|
switch (baseType) {
|
||||||
|
case 'BTC':
|
||||||
|
usdValue = balance * prices.btc;
|
||||||
|
break;
|
||||||
|
case 'LTC':
|
||||||
|
usdValue = balance * prices.ltc;
|
||||||
|
break;
|
||||||
|
case 'ETH':
|
||||||
|
usdValue = balance * prices.eth;
|
||||||
|
break;
|
||||||
|
case 'USDT':
|
||||||
|
usdValue = balance; // USDT привязан к доллару
|
||||||
|
break;
|
||||||
|
case 'USDC':
|
||||||
|
usdValue = balance; // USDC привязан к доллару
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const walletUtilsInstance = new WalletUtils(
|
// Форматируем дату архивации (если кошелек архивный)
|
||||||
wallet.wallet_type === 'BTC' ? wallet.address : null,
|
let archivedDate = '';
|
||||||
wallet.wallet_type === 'LTC' ? wallet.address : null,
|
if (wallet.wallet_type.includes('_')) {
|
||||||
wallet.wallet_type === 'ETH' || wallet.wallet_type === 'USDT' || wallet.wallet_type === 'USDC' ? wallet.address : null,
|
const timestamp = wallet.wallet_type.split('_')[1];
|
||||||
null, // userId не нужен для админки
|
if (timestamp) {
|
||||||
Date.now() - 30 * 24 * 60 * 60 * 1000
|
const date = new Date(parseInt(timestamp));
|
||||||
);
|
archivedDate = date.toLocaleString();
|
||||||
|
}
|
||||||
const balances = await walletUtilsInstance.getAllBalances();
|
}
|
||||||
const balance = balances[wallet.wallet_type] || { amount: 0, usdValue: 0 };
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
address: wallet.address,
|
address: wallet.address,
|
||||||
balance: balance.amount.toFixed(8),
|
balance: balance.toFixed(8),
|
||||||
mnemonic: wallet.mnemonic
|
usdValue: usdValue.toFixed(2),
|
||||||
|
status: wallet.wallet_type.includes('_') ? 'Archived' : 'Active',
|
||||||
|
archivedDate: archivedDate
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Убираем null значения из массива
|
|
||||||
const filteredWallets = walletsWithData.filter(wallet => wallet !== null);
|
|
||||||
|
|
||||||
// Создаем CSV-файл
|
// Создаем CSV-файл
|
||||||
const csv = csvWriter.createObjectCsvWriter({
|
const csv = csvWriter.createObjectCsvWriter({
|
||||||
path: `wallets_${walletType}.csv`,
|
path: `wallets_${walletType}.csv`,
|
||||||
header: [
|
header: [
|
||||||
{ id: 'address', title: 'Address' },
|
{ id: 'address', title: 'Address' },
|
||||||
{ id: 'balance', title: 'Balance' },
|
{ id: 'balance', title: 'Balance' },
|
||||||
{ id: 'mnemonic', title: 'Mnemonic' }
|
{ id: 'usdValue', title: 'Value (USD)' },
|
||||||
|
{ id: 'status', title: 'Status' },
|
||||||
|
{ id: 'archivedDate', title: 'Archived Date' }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
await csv.writeRecords(filteredWallets);
|
await csv.writeRecords(walletsWithData);
|
||||||
|
|
||||||
// Отправляем файл пользователю
|
// Отправляем файл пользователю
|
||||||
await bot.sendDocument(chatId, fs.createReadStream(`wallets_${walletType}.csv`));
|
await bot.sendDocument(chatId, fs.createReadStream(`wallets_${walletType}.csv`));
|
||||||
|
|
||||||
// Удаляем временный файл
|
// Удаляем временный файл
|
||||||
fs.unlinkSync(`wallets_${walletType}.csv`);
|
fs.unlinkSync(`wallets_${walletType}.csv`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Wallet.js
|
||||||
|
|
||||||
import db from "../config/database.js";
|
import db from "../config/database.js";
|
||||||
import WalletUtils from "../utils/walletUtils.js";
|
import WalletUtils from "../utils/walletUtils.js";
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// walletGenerator.js
|
||||||
|
|
||||||
|
|
||||||
import bip39 from 'bip39';
|
import bip39 from 'bip39';
|
||||||
import HDKey from 'hdkey';
|
import HDKey from 'hdkey';
|
||||||
import { publicToAddress } from 'ethereumjs-util';
|
import { publicToAddress } from 'ethereumjs-util';
|
||||||
|
|||||||
@@ -76,7 +76,17 @@ export default class WalletUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getBaseWalletType(walletType) {
|
static getBaseWalletType(walletType) {
|
||||||
if (walletType.includes('ERC-20')) return 'ETH';
|
// Убираем суффикс ERC-20, если он есть
|
||||||
|
if (walletType.includes('ERC-20')) {
|
||||||
|
return 'ETH';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Убираем суффикс с таймштампом (например, USDT_1735846098129 -> USDT)
|
||||||
|
if (walletType.includes('_')) {
|
||||||
|
return walletType.split('_')[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращаем исходный тип, если это не ERC-20 и не архивный кошелек
|
||||||
return walletType;
|
return walletType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user