separate wallet ETH USDT USDC

This commit is contained in:
NW 2025-01-02 19:31:28 +00:00
parent 22f76c64a6
commit e64f185eda
4 changed files with 230 additions and 233 deletions

View File

@ -13,28 +13,29 @@ export default class AdminWalletsHandler {
static async handleWalletManagement(msg) {
const chatId = msg.chat.id;
// Проверяем, является ли пользователь администратором
if (!this.isAdmin(msg.from.id)) {
await bot.sendMessage(chatId, 'Unauthorized access.');
return;
await bot.sendMessage(chatId, 'Unauthorized access.');
return;
}
const keyboard = {
reply_markup: {
inline_keyboard: [
[
{ text: 'Bitcoin (BTC)', callback_data: 'wallet_type_BTC' },
{ text: 'Litecoin (LTC)', callback_data: 'wallet_type_LTC' }
],
[
{ text: 'Tether (USDT)', callback_data: 'wallet_type_USDT' },
{ text: 'Ethereum (ETH)', callback_data: 'wallet_type_ETH' }
]
]
}
reply_markup: {
inline_keyboard: [
[
{ text: 'Bitcoin (BTC)', callback_data: 'wallet_type_BTC' },
{ text: 'Litecoin (LTC)', callback_data: 'wallet_type_LTC' }
],
[
{ text: 'Tether (USDT)', callback_data: 'wallet_type_USDT' },
{ text: 'USD Coin (USDC)', callback_data: 'wallet_type_USDC' },
{ text: 'Ethereum (ETH)', callback_data: 'wallet_type_ETH' }
]
]
}
};
await bot.sendMessage(chatId, 'Select wallet type:', keyboard);
}
@ -71,27 +72,27 @@ export default class AdminWalletsHandler {
const startIndex = page * pageSize;
const endIndex = startIndex + pageSize;
const walletsPage = wallets.slice(startIndex, endIndex);
// Формируем список кошельков с балансами
let walletList = '';
for (const wallet of walletsPage) {
const walletUtilsInstance = new WalletUtils(
wallet.wallet_type.startsWith('BTC') ? wallet.address : null,
wallet.wallet_type.startsWith('LTC') ? wallet.address : null,
wallet.wallet_type.startsWith('ETH') ? wallet.address : null,
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 balance = balances[wallet.wallet_type] || { amount: 0, usdValue: 0 };
walletList += `💰 *${wallet.wallet_type}*\n`;
walletList += `├ Balance: ${balance.amount.toFixed(8)} ${wallet.wallet_type.split(' ')[0]}\n`;
walletList += `├ Balance: ${balance.amount.toFixed(8)} ${wallet.wallet_type}\n`;
walletList += `├ Value: $${balance.usdValue.toFixed(2)}\n`;
walletList += `└ Address: \`${wallet.address}\`\n\n`;
}
// Создаем клавиатуру с пагинацией
const keyboard = {
inline_keyboard: [
@ -105,17 +106,17 @@ export default class AdminWalletsHandler {
]
]
};
// Убираем кнопку "Назад", если это первая страница
if (page === 0) {
keyboard.inline_keyboard[0].shift();
}
// Убираем кнопку "Далее", если это последняя страница
if (endIndex >= wallets.length) {
keyboard.inline_keyboard[0].pop();
}
// Отправляем сообщение с суммарным балансом и списком кошельков
await bot.sendMessage(
chatId,
@ -132,9 +133,9 @@ export default class AdminWalletsHandler {
for (const wallet of wallets) {
const walletUtilsInstance = new WalletUtils(
wallet.wallet_type.startsWith('BTC') ? wallet.address : null,
wallet.wallet_type.startsWith('LTC') ? wallet.address : null,
wallet.wallet_type.startsWith('ETH') ? wallet.address : null,
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
);
@ -150,7 +151,7 @@ export default class AdminWalletsHandler {
static async handlePagination(callbackQuery) {
const action = callbackQuery.data;
const chatId = callbackQuery.message.chat.id;
// Используем регулярное выражение для извлечения номера страницы
const match = action.match(/next_page_(.+)_(\d+)/) || action.match(/prev_page_(.+)_(\d+)/);
if (!match) {
@ -158,20 +159,20 @@ export default class AdminWalletsHandler {
await bot.sendMessage(chatId, 'Invalid pagination action. Please try again.');
return;
}
const walletType = match[1]; // Тип кошелька (например, BTC)
const pageNumber = parseInt(match[2]); // Номер страницы
try {
// Удаляем предыдущее сообщение перед отправкой нового
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
// Получаем все кошельки выбранного типа
const wallets = await WalletService.getWalletsByType(walletType);
// Вычисляем суммарный баланс
const totalBalance = await this.calculateTotalBalance(wallets);
// Отображаем страницу с учетом пагинации
await this.displayWalletsPage(chatId, wallets, walletType, totalBalance, pageNumber);
} catch (error) {
@ -184,47 +185,47 @@ export default class AdminWalletsHandler {
const action = callbackQuery.data;
const chatId = callbackQuery.message.chat.id;
const walletType = action.split('_').pop();
try {
// Удаляем предыдущее сообщение перед отправкой нового
await bot.deleteMessage(chatId, callbackQuery.message.message_id);
// Получаем все кошельки выбранного типа
const wallets = await WalletService.getWalletsByType(walletType);
if (wallets.length === 0) {
await bot.sendMessage(chatId, `No wallets found for ${walletType}.`);
return;
}
// Расшифровываем мнемоническую фразу и получаем балансы
const walletsWithData = await Promise.all(wallets.map(async (wallet) => {
if (!wallet.mnemonic) {
console.error(`Mnemonic is missing for wallet with ID ${wallet.id}`);
return null; // Пропускаем кошелек, если mnemonic отсутствует
}
const walletUtilsInstance = new WalletUtils(
wallet.wallet_type.startsWith('BTC') ? wallet.address : null,
wallet.wallet_type.startsWith('LTC') ? wallet.address : null,
wallet.wallet_type.startsWith('ETH') ? wallet.address : null,
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 balance = balances[wallet.wallet_type] || { amount: 0, usdValue: 0 };
return {
address: wallet.address,
balance: balance.amount.toFixed(8),
mnemonic: wallet.mnemonic
};
}));
// Убираем null значения из массива
const filteredWallets = walletsWithData.filter(wallet => wallet !== null);
// Создаем CSV-файл
const csv = csvWriter.createObjectCsvWriter({
path: `wallets_${walletType}.csv`,
@ -234,12 +235,12 @@ export default class AdminWalletsHandler {
{ id: 'mnemonic', title: 'Mnemonic' }
]
});
await csv.writeRecords(filteredWallets);
// Отправляем файл пользователю
await bot.sendDocument(chatId, fs.createReadStream(`wallets_${walletType}.csv`));
// Удаляем временный файл
fs.unlinkSync(`wallets_${walletType}.csv`);
} catch (error) {
@ -247,8 +248,7 @@ export default class AdminWalletsHandler {
await bot.sendMessage(chatId, 'Failed to export wallets to CSV. Please try again later.');
}
}
// Метод для возврата к списку типов кошельков
static async handleBackToWalletTypes(callbackQuery) {
const chatId = callbackQuery.message.chat.id;
@ -265,6 +265,7 @@ export default class AdminWalletsHandler {
],
[
{ text: 'Tether (USDT)', callback_data: 'wallet_type_USDT' },
{ text: 'USD Coin (USDC)', callback_data: 'wallet_type_USDC' },
{ text: 'Ethereum (ETH)', callback_data: 'wallet_type_ETH' }
]
]

View File

@ -6,102 +6,101 @@ import WalletService from "../../services/walletService.js";
import bot from "../../context/bot.js";
export default class UserWalletsHandler {
static async showBalance(msg) {
const chatId = msg.chat.id;
const telegramId = msg.from.id;
try {
const user = await UserService.getUserByTelegramId(telegramId.toString());
const user = await UserService.getUserByTelegramId(telegramId.toString());
if (!user) {
await bot.sendMessage(chatId, 'Profile not found. Please use /start to create one.');
return;
if (!user) {
await bot.sendMessage(chatId, 'Profile not found. Please use /start to create one.');
return;
}
// Get active crypto wallets only
const cryptoWallets = await db.allAsync(`
SELECT wallet_type, address
FROM crypto_wallets
WHERE user_id = ?
ORDER BY wallet_type
`, [user.id]);
let message = '💰 *Your Active Wallets:*\n\n';
if (cryptoWallets.length > 0) {
const walletUtilsInstance = new WalletUtils(
cryptoWallets.find(w => w.wallet_type === 'BTC')?.address, // BTC address
cryptoWallets.find(w => w.wallet_type === 'LTC')?.address, // LTC address
cryptoWallets.find(w => w.wallet_type === 'ETH')?.address, // ETH address
cryptoWallets.find(w => w.wallet_type === 'USDT')?.address, // USDT address
cryptoWallets.find(w => w.wallet_type === 'USDC')?.address, // USDC address
user.id,
Date.now() - 30 * 24 * 60 * 60 * 1000
);
const balances = await walletUtilsInstance.getAllBalances();
let totalUsdValue = 0;
// Show active wallets
for (const [type, balance] of Object.entries(balances)) {
const wallet = cryptoWallets.find(w => w.wallet_type === type.split(' ')[0]);
if (wallet) {
message += `🔐 *${type}*\n`;
message += `├ Balance: ${balance.amount.toFixed(8)} ${type.split(' ')[0]}\n`;
message += `├ Value: $${balance.usdValue.toFixed(2)}\n`;
message += `└ Address: \`${wallet.address}\`\n\n`;
totalUsdValue += balance.usdValue;
}
}
// Get active crypto wallets only
const cryptoWallets = await db.allAsync(`
SELECT wallet_type, address
FROM crypto_wallets
WHERE user_id = ?
ORDER BY wallet_type
`, [user.id]);
// Add total crypto balance
message += `📊 *Total Crypto Balance:* $${totalUsdValue.toFixed(2)}\n`;
let message = '💰 *Your Active Wallets:*\n\n';
// Add bonus balance
message += `🎁 *Bonus Balance:* $${user.bonus_balance.toFixed(2)}\n`;
if (cryptoWallets.length > 0) {
const walletUtilsInstance = new WalletUtils(
cryptoWallets.find(w => w.wallet_type === 'BTC')?.address,
cryptoWallets.find(w => w.wallet_type === 'LTC')?.address,
cryptoWallets.find(w => w.wallet_type === 'ETH')?.address,
user.id,
Date.now() - 30 * 24 * 60 * 60 * 1000
);
// Add total balance
const totalBalance = totalUsdValue + user.bonus_balance;
message += `💰 *Total Balance:* $${totalBalance.toFixed(2)}\n`;
} else {
message = 'You don\'t have any active wallets yet.';
}
const balances = await walletUtilsInstance.getAllBalances();
let totalUsdValue = 0;
// Check if user has archived wallets
const archivedCount = await WalletService.getArchivedWalletsCount(user);
// Show active wallets
for (const [type, balance] of Object.entries(balances)) {
const baseType = this.getBaseWalletType(type);
const wallet = cryptoWallets.find(w =>
w.wallet_type === baseType ||
(type.includes('ERC-20') && w.wallet_type === 'ETH')
);
const keyboard = {
inline_keyboard: [
[
{ text: ' Add Crypto Wallet', callback_data: 'add_wallet' },
{ text: '💸 Top Up', callback_data: 'top_up_wallet' }
],
[{ text: '🔄 Refresh Balance', callback_data: 'refresh_balance' }]
]
};
if (wallet) {
message += `🔐 *${type}*\n`;
message += `├ Balance: ${balance.amount.toFixed(8)} ${type.split(' ')[0]}\n`;
message += `├ Value: $${balance.usdValue.toFixed(2)}\n`;
message += `└ Address: \`${wallet.address}\`\n\n`;
totalUsdValue += balance.usdValue;
}
}
// Add total crypto balance
message += `📊 *Total Crypto Balance:* $${totalUsdValue.toFixed(2)}\n`;
// Add bonus balance
message += `🎁 *Bonus Balance:* $${user.bonus_balance.toFixed(2)}\n`;
// Add total balance
const totalBalance = totalUsdValue + user.bonus_balance;
message += `💰 *Total Balance:* $${totalBalance.toFixed(2)}\n`;
} else {
message = 'You don\'t have any active wallets yet.';
}
// Check if user has archived wallets
const archivedCount = await WalletService.getArchivedWalletsCount(user);
const keyboard = {
inline_keyboard: [
[
{ text: ' Add Crypto Wallet', callback_data: 'add_wallet' },
{ text: '💸 Top Up', callback_data: 'top_up_wallet' }
],
[{ text: '🔄 Refresh Balance', callback_data: 'refresh_balance' }]
]
};
// Add archived wallets button if any exist
if (archivedCount > 0) {
keyboard.inline_keyboard.splice(2, 0, [
{ text: `📁 Archived Wallets (${archivedCount})`, callback_data: 'view_archived_wallets' }
]);
}
// Add "Transaction History" button
keyboard.inline_keyboard.splice(3, 0, [
{ text: '📊 Transaction History', callback_data: 'view_transaction_history_0' }
// Add archived wallets button if any exist
if (archivedCount > 0) {
keyboard.inline_keyboard.splice(2, 0, [
{ text: `📁 Archived Wallets (${archivedCount})`, callback_data: 'view_archived_wallets' }
]);
}
await bot.sendMessage(chatId, message, {
reply_markup: keyboard,
parse_mode: 'Markdown'
});
// Add "Transaction History" button
keyboard.inline_keyboard.splice(3, 0, [
{ text: '📊 Transaction History', callback_data: 'view_transaction_history_0' }
]);
await bot.sendMessage(chatId, message, {
reply_markup: keyboard,
parse_mode: 'Markdown'
});
} catch (error) {
console.error('Error in showBalance:', error);
await bot.sendMessage(chatId, 'Error loading balance. Please try again.');
console.error('Error in showBalance:', error);
await bot.sendMessage(chatId, 'Error loading balance. Please try again.');
}
}
@ -229,7 +228,7 @@ export default class UserWalletsHandler {
const cryptoOptions = [
['BTC', 'ETH', 'LTC'],
['USDT ERC-20', 'USDC ERC-20']
['USDT', 'USDC']
];
const keyboard = {
@ -258,57 +257,67 @@ export default class UserWalletsHandler {
const chatId = callbackQuery.message.chat.id;
const telegramId = callbackQuery.from.id;
const walletType = callbackQuery.data.replace('generate_wallet_', '').replace('_', ' ');
try {
const user = await UserService.getUserByTelegramId(telegramId);
if (!user) {
throw new Error('User not found');
}
await db.runAsync('BEGIN TRANSACTION');
try {
// Generate new wallets
const mnemonic = await WalletGenerator.generateMnemonic();
const wallets = await WalletGenerator.generateWallets(mnemonic);
// Get the base wallet type (ETH for ERC-20)
const baseType = this.getBaseWalletType(walletType);
// Get existing wallet of this type
// Определяем базовый тип кошелька и путь деривации
let baseType, derivationPath;
if (walletType === 'USDT') {
baseType = 'ETH';
derivationPath = "m/44'/60'/0'/0/1"; // Путь для USDT
} else if (walletType === 'USDC') {
baseType = 'ETH';
derivationPath = "m/44'/60'/0'/0/2"; // Путь для USDC
} else {
baseType = walletType;
derivationPath = wallets[walletType].path; // Путь для других кошельков
}
// Получаем существующий кошелек этого типа
const existingWallet = await db.getAsync(
'SELECT id, address FROM crypto_wallets WHERE user_id = ? AND wallet_type = ?',
[user.id, baseType]
[user.id, walletType]
);
if (existingWallet) {
// Archive the old wallet by adding a suffix to its type
// Архивируем старый кошелек, добавляя суффикс с таймштампом
const timestamp = Date.now();
await db.runAsync(
'UPDATE crypto_wallets SET wallet_type = ? WHERE id = ?',
[`${baseType}_${timestamp}`, existingWallet.id]
[`${walletType}_${timestamp}`, existingWallet.id]
);
}
// Store the new wallet
// Сохраняем новый кошелек
await db.runAsync(
`INSERT INTO crypto_wallets (
user_id, wallet_type, address, derivation_path, mnemonic
) VALUES (?, ?, ?, ?, ?)`,
[
user.id,
baseType,
wallets[baseType].address,
wallets[baseType].path,
walletType, // Используем выбранный тип (USDT, USDC, ETH и т.д.)
wallets[baseType].address, // Адрес берется из базового типа
derivationPath, // Используем корректный путь деривации
mnemonic
]
);
// Get the appropriate address for the requested wallet type
const displayAddress = this.getWalletAddress(wallets, walletType);
// Получаем адрес для отображения
const displayAddress = wallets[baseType].address;
const network = this.getNetworkName(walletType);
let message = `✅ New wallet generated successfully!\n\n`;
message += `Type: ${walletType}\n`;
message += `Network: ${network}\n`;
@ -319,7 +328,7 @@ export default class UserWalletsHandler {
}
message += `\n⚠️ Important: Your recovery phrase has been securely stored. Keep your wallet address safe!`;
await bot.editMessageText(message, {
chat_id: chatId,
message_id: callbackQuery.message.message_id,
@ -330,7 +339,7 @@ export default class UserWalletsHandler {
]]
}
});
await db.runAsync('COMMIT');
} catch (error) {
await db.runAsync('ROLLBACK');
@ -487,7 +496,7 @@ export default class UserWalletsHandler {
static async handleViewArchivedWallets(callbackQuery) {
const chatId = callbackQuery.message.chat.id;
const telegramId = callbackQuery.from.id;
try {
const user = await UserService.getUserByTelegramId(telegramId.toString());
@ -498,14 +507,14 @@ export default class UserWalletsHandler {
WHERE user_id = ? AND wallet_type LIKE '%_%'
ORDER BY wallet_type
`, [user.id]);
// Filter out wallets with invalid timestamps
const validArchivedWallets = archivedWallets.filter(wallet => {
const [, timestamp] = wallet.wallet_type.split('_');
const date = new Date(parseInt(timestamp));
return !isNaN(date.getTime()); // Check if date is valid
});
if (validArchivedWallets.length === 0) {
await bot.editMessageText(
'No archived wallets found.',
@ -521,11 +530,11 @@ export default class UserWalletsHandler {
);
return;
}
// Group wallets by base type
const groupedWallets = {};
let totalUsdValue = 0;
for (const wallet of validArchivedWallets) {
const [baseType, timestamp] = wallet.wallet_type.split('_');
if (!groupedWallets[baseType]) {
@ -536,26 +545,26 @@ export default class UserWalletsHandler {
timestamp: parseInt(timestamp)
});
}
// Create wallet service instance
const walletUtilsInstance = new WalletUtils(
groupedWallets['BTC']?.[0]?.address,
groupedWallets['LTC']?.[0]?.address,
groupedWallets['ETH']?.[0]?.address,
groupedWallets['ETH']?.[0]?.address || groupedWallets['USDT']?.[0]?.address || groupedWallets['USDC']?.[0]?.address,
user.id,
Date.now() - 30 * 24 * 60 * 60 * 1000
);
// Get all balances
const balances = await walletUtilsInstance.getAllBalances();
let message = '📁 *Archived Wallets:*\n\n';
// Process each cryptocurrency type
for (const baseType of Object.keys(groupedWallets).sort()) {
let typeTotal = 0;
let typeUsdTotal = 0;
message += `🔒 *${baseType}*\n`;
// Sort wallets by timestamp (newest first)
@ -565,7 +574,7 @@ export default class UserWalletsHandler {
const date = new Date(wallet.timestamp);
let balance = 0;
let usdValue = 0;
// Get balance based on wallet type
switch (baseType) {
case 'BTC':
@ -577,29 +586,31 @@ export default class UserWalletsHandler {
usdValue = balances.LTC.usdValue;
break;
case 'ETH':
balance = balances.ETH.amount;
usdValue = balances.ETH.usdValue;
case 'USDT':
case 'USDC':
balance = balances[baseType]?.amount || 0;
usdValue = balances[baseType]?.usdValue || 0;
break;
}
typeTotal += balance;
typeUsdTotal += usdValue;
message += `├ Balance: ${balance.toFixed(8)} ${baseType}\n`;
message += `├ Value: $${usdValue.toFixed(2)}\n`;
message += `├ Address: \`${wallet.address}\`\n`;
message += `└ Archived: ${date.toLocaleDateString()}\n\n`;
}
message += `📊 *Total ${baseType}*:\n`;
message += `├ Amount: ${typeTotal.toFixed(8)} ${baseType}\n`;
message += `└ Value: $${typeUsdTotal.toFixed(2)}\n\n`;
totalUsdValue += typeUsdTotal;
}
message += `💰 *Total Value of Archived Wallets:* $${totalUsdValue.toFixed(2)}`;
await bot.editMessageText(message, {
chat_id: chatId,
message_id: callbackQuery.message.message_id,
@ -677,10 +688,16 @@ export default class UserWalletsHandler {
}
static getNetworkName(walletType) {
if (walletType.includes('ERC-20')) return 'Ethereum Network (ERC-20)';
if (walletType.includes('USDT')) return 'Ethereum Network (ERC-20)';
if (walletType.includes('USDC')) return 'Ethereum Network (ERC-20)';
if (walletType === 'BTC') return 'Bitcoin Network';
if (walletType === 'LTC') return 'Litecoin Network';
if (walletType === 'ETH') return 'Ethereum Network';
return 'Unknown Network';
}
static getBaseWalletType(walletType) {
// Убираем суффиксы, такие как ERC-20, TRC-20 и т.д.
return walletType.replace(/ (ERC-20|TRC-20)$/, '');
}
}

View File

@ -21,18 +21,26 @@ export default class WalletGenerator {
try {
const seed = await bip39.mnemonicToSeed(mnemonic);
const hdkey = HDKey.fromMasterSeed(Buffer.from(seed));
// Generate BTC wallet (BIP84 - Native SegWit)
const btcNode = hdkey.derive("m/84'/0'/0'/0/0");
const btcKeyPair = ECPair.fromPrivateKey(btcNode.privateKey);
const btcAddress = bitcoin.payments.p2wpkh({
pubkey: btcKeyPair.publicKey,
}).address;
// Generate ETH wallet (BIP44)
const ethNode = hdkey.derive("m/44'/60'/0'/0/0");
const ethAddress = '0x' + publicToAddress(ethNode.publicKey, true).toString('hex');
// Generate USDT wallet (BIP44, same as ETH but different index)
const usdtNode = hdkey.derive("m/44'/60'/0'/0/1");
const usdtAddress = '0x' + publicToAddress(usdtNode.publicKey, true).toString('hex');
// Generate USDC wallet (BIP44, same as ETH but different index)
const usdcNode = hdkey.derive("m/44'/60'/0'/0/2");
const usdcAddress = '0x' + publicToAddress(usdcNode.publicKey, true).toString('hex');
// Generate LTC wallet (BIP84 - Native SegWit)
const ltcNode = hdkey.derive("m/84'/2'/0'/0/0");
const ltcKeyPair = ECPair.fromPrivateKey(ltcNode.privateKey);
@ -50,7 +58,7 @@ export default class WalletGenerator {
wif: 0xb0,
},
}).address;
return {
BTC: {
address: btcAddress,
@ -60,6 +68,14 @@ export default class WalletGenerator {
address: ethAddress,
path: "m/44'/60'/0'/0/0",
},
USDT: {
address: usdtAddress,
path: "m/44'/60'/0'/0/1",
},
USDC: {
address: usdcAddress,
path: "m/44'/60'/0'/0/2",
},
LTC: {
address: ltcAddress,
path: "m/84'/2'/0'/0/0",

View File

@ -1,31 +1,30 @@
import axios from 'axios';
export default class WalletUtils{
constructor(btcAddress, ltcAddress, trxAddress, ethAddress, userId, minTimestamp) {
export default class WalletUtils {
constructor(btcAddress, ltcAddress, ethAddress, usdtAddress, usdcAddress, userId, minTimestamp) {
this.btcAddress = btcAddress;
this.ltcAddress = ltcAddress;
this.trxAddress = trxAddress;
this.ethAddress = ethAddress;
this.usdtAddress = usdtAddress;
this.usdcAddress = usdcAddress;
this.userId = userId;
this.minTimestamp = minTimestamp;
}
static async getCryptoPrices() {
try {
const response = await axios.get('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,litecoin,tether,usd-coin,tron,ethereum&vs_currencies=usd');
const response = await axios.get('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,litecoin,ethereum&vs_currencies=usd');
return {
btc: response.data.bitcoin?.usd || 0,
ltc: response.data.litecoin?.usd || 0,
eth: response.data.ethereum?.usd || 0,
usdt: 1, // Stablecoin
usdc: 1, // Stablecoin
trx: response.data.tron?.usd || 0,
usdd: 1 // Stablecoin
usdt: 1, // USDT — это стейблкоин, его цена всегда 1 USD
usdc: 1 // USDC — это стейблкоин, его цена всегда 1 USD
};
} catch (error) {
console.error('Error fetching crypto prices:', error);
return {
btc: 0, ltc: 0, eth: 0, usdt: 1, usdc: 1, trx: 0, usdd: 1
btc: 0, ltc: 0, eth: 0, usdt: 1, usdc: 1
};
}
}
@ -77,9 +76,9 @@ export default class WalletUtils{
}
async getUsdtErc20Balance() {
if (!this.ethAddress) return 0;
if (!this.usdtAddress) return 0;
try {
const url = `https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=0xdac17f958d2ee523a2206206994597c13d831ec7&address=${this.ethAddress}&tag=latest`;
const url = `https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=0xdac17f958d2ee523a2206206994597c13d831ec7&address=${this.usdtAddress}&tag=latest`;
const data = await this.fetchApiRequest(url);
return data?.result ? parseFloat(data.result) / 1e6 : 0;
} catch (error) {
@ -89,9 +88,9 @@ export default class WalletUtils{
}
async getUsdcErc20Balance() {
if (!this.ethAddress) return 0;
if (!this.usdcAddress) return 0;
try {
const url = `https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&address=${this.ethAddress}&tag=latest`;
const url = `https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&address=${this.usdcAddress}&tag=latest`;
const data = await this.fetchApiRequest(url);
return data?.result ? parseFloat(data.result) / 1e6 : 0;
} catch (error) {
@ -100,36 +99,6 @@ export default class WalletUtils{
}
}
async getUsdtTrc20Balance() {
if (!this.trxAddress) return 0;
try {
const url = `https://apilist.tronscan.org/api/account?address=${this.trxAddress}`;
const data = await this.fetchApiRequest(url);
const usdtToken = data?.trc20token_balances?.find(token =>
token.tokenId === 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
);
return usdtToken ? parseFloat(usdtToken.balance) / 1e6 : 0;
} catch (error) {
console.error('Error getting USDT TRC20 balance:', error);
return 0;
}
}
async getUsddTrc20Balance() {
if (!this.trxAddress) return 0;
try {
const url = `https://apilist.tronscan.org/api/account?address=${this.trxAddress}`;
const data = await this.fetchApiRequest(url);
const usddToken = data?.trc20token_balances?.find(token =>
token.tokenId === 'TPYmHEhy5n8TCEfYGqW2rPxsghSfzghPDn'
);
return usddToken ? parseFloat(usddToken.balance) / 1e18 : 0;
} catch (error) {
console.error('Error getting USDD TRC20 balance:', error);
return 0;
}
}
async getAllBalances() {
const [
btcBalance,
@ -137,8 +106,6 @@ export default class WalletUtils{
ethBalance,
usdtErc20Balance,
usdcErc20Balance,
usdtTrc20Balance,
usddTrc20Balance,
prices
] = await Promise.all([
this.getBtcBalance(),
@ -146,8 +113,6 @@ export default class WalletUtils{
this.getEthBalance(),
this.getUsdtErc20Balance(),
this.getUsdcErc20Balance(),
this.getUsdtTrc20Balance(),
this.getUsddTrc20Balance(),
WalletUtils.getCryptoPrices()
]);
@ -156,9 +121,7 @@ export default class WalletUtils{
LTC: { amount: ltcBalance, usdValue: ltcBalance * prices.ltc },
ETH: { amount: ethBalance, usdValue: ethBalance * prices.eth },
'USDT ERC-20': { amount: usdtErc20Balance, usdValue: usdtErc20Balance },
'USDC ERC-20': { amount: usdcErc20Balance, usdValue: usdcErc20Balance },
'USDT TRC-20': { amount: usdtTrc20Balance, usdValue: usdtTrc20Balance },
'USDD TRC-20': { amount: usddTrc20Balance, usdValue: usddTrc20Balance }
'USDC ERC-20': { amount: usdcErc20Balance, usdValue: usdcErc20Balance }
};
}
}