crypto mnemonic case
This commit is contained in:
parent
24aebd0bcf
commit
fa09e81ddf
@ -2,5 +2,6 @@ export default {
|
||||
BOT_TOKEN: process.env.BOT_TOKEN,
|
||||
ADMIN_IDS: process.env.ADMIN_IDS.split(","),
|
||||
SUPPORT_LINK: process.env.SUPPORT_LINK,
|
||||
CATALOG_PATH: process.env.CATALOG_PATH
|
||||
CATALOG_PATH: process.env.CATALOG_PATH,
|
||||
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY || 'U9845jugfdyt87435tg34byusd'
|
||||
};
|
@ -293,12 +293,24 @@ export default class AdminWalletsHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем расшифрованную мнемоническую фразу, если она есть
|
||||
let mnemonic = '';
|
||||
if (wallet.mnemonic) {
|
||||
try {
|
||||
mnemonic = await WalletService.decryptMnemonic(wallet.mnemonic, wallet.user_id);
|
||||
} catch (error) {
|
||||
console.error('Error decrypting mnemonic:', error);
|
||||
mnemonic = '[DECRYPTION FAILED]';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
address: wallet.address,
|
||||
balance: balance.toFixed(8),
|
||||
usdValue: usdValue.toFixed(2),
|
||||
status: wallet.wallet_type.includes('_') ? 'Archived' : 'Active',
|
||||
archivedDate: archivedDate
|
||||
archivedDate: archivedDate,
|
||||
mnemonic: mnemonic
|
||||
};
|
||||
}));
|
||||
|
||||
@ -310,7 +322,8 @@ export default class AdminWalletsHandler {
|
||||
{ id: 'balance', title: 'Balance' },
|
||||
{ id: 'usdValue', title: 'Value (USD)' },
|
||||
{ id: 'status', title: 'Status' },
|
||||
{ id: 'archivedDate', title: 'Archived Date' }
|
||||
{ id: 'archivedDate', title: 'Archived Date' },
|
||||
{ id: 'mnemonic', title: 'Mnemonic Phrase' }
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -365,23 +365,6 @@ export default class UserWalletsHandler {
|
||||
await db.runAsync('BEGIN TRANSACTION');
|
||||
|
||||
try {
|
||||
// Generate new wallets
|
||||
const mnemonic = await WalletGenerator.generateMnemonic();
|
||||
const wallets = await WalletGenerator.generateWallets(mnemonic);
|
||||
|
||||
// Определяем базовый тип кошелька и путь деривации
|
||||
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 = ?',
|
||||
@ -397,24 +380,30 @@ export default class UserWalletsHandler {
|
||||
);
|
||||
}
|
||||
|
||||
// Сохраняем новый кошелек
|
||||
await db.runAsync(
|
||||
`INSERT INTO crypto_wallets (
|
||||
user_id, wallet_type, address, derivation_path, mnemonic
|
||||
) VALUES (?, ?, ?, ?, ?)`,
|
||||
[
|
||||
user.id,
|
||||
walletType, // Используем выбранный тип (USDT, USDC, ETH и т.д.)
|
||||
wallets[baseType].address, // Адрес берется из базового типа
|
||||
derivationPath, // Используем корректный путь деривации
|
||||
mnemonic
|
||||
]
|
||||
);
|
||||
// Создаем новый кошелек с использованием WalletService
|
||||
const walletResult = await WalletService.createWallet(user.id, walletType);
|
||||
|
||||
if (!walletResult || !walletResult.address) {
|
||||
console.error('Wallet creation failed:', {
|
||||
error: walletResult,
|
||||
userId: user.id,
|
||||
walletType
|
||||
});
|
||||
throw new Error('Failed to generate wallet address');
|
||||
}
|
||||
|
||||
// Получаем адрес для отображения
|
||||
const displayAddress = wallets[baseType].address;
|
||||
const displayAddress = walletResult.address;
|
||||
const network = this.getNetworkName(walletType);
|
||||
|
||||
console.log('Wallet created successfully:', {
|
||||
address: displayAddress,
|
||||
derivationPath: walletResult.derivationPath,
|
||||
userId: user.id,
|
||||
walletType,
|
||||
network
|
||||
});
|
||||
|
||||
let message = `✅ New wallet generated successfully!\n\n`;
|
||||
message += `Type: ${walletType}\n`;
|
||||
message += `Network: ${network}\n`;
|
||||
|
@ -1,7 +1,10 @@
|
||||
// walletService.js
|
||||
|
||||
import db from "../config/database.js";
|
||||
import config from "../config/config.js";
|
||||
import WalletUtils from "../utils/walletUtils.js";
|
||||
import WalletGenerator from "../utils/walletGenerator.js";
|
||||
import crypto from 'crypto';
|
||||
|
||||
class WalletService {
|
||||
static async getArchivedWalletsCount(user) {
|
||||
@ -119,6 +122,187 @@ class WalletService {
|
||||
throw new Error('Failed to fetch wallets by type');
|
||||
}
|
||||
}
|
||||
|
||||
static async createWallet(userId, walletType) {
|
||||
try {
|
||||
// Генерация нового кошелька
|
||||
const mnemonic = await WalletGenerator.generateMnemonic();
|
||||
const wallets = await WalletGenerator.generateWallets(mnemonic, userId);
|
||||
|
||||
if (!wallets || typeof wallets !== 'object') {
|
||||
throw new Error('Failed to generate wallets');
|
||||
}
|
||||
|
||||
// Проверяем наличие базового типа кошелька
|
||||
const baseType = walletType === 'USDT' || walletType === 'USDC' ? 'ETH' : walletType;
|
||||
if (!wallets[baseType.toUpperCase()]) {
|
||||
throw new Error(`Unsupported wallet type: ${walletType}`);
|
||||
}
|
||||
|
||||
// Проверяем наличие ключа шифрования
|
||||
if (!config.ENCRYPTION_KEY || typeof config.ENCRYPTION_KEY !== 'string') {
|
||||
throw new Error('Encryption key is not configured');
|
||||
}
|
||||
|
||||
// Проверяем и преобразуем userId
|
||||
if (typeof userId !== 'number' && typeof userId !== 'string') {
|
||||
throw new Error('Invalid user ID');
|
||||
}
|
||||
const userIdStr = userId.toString();
|
||||
|
||||
// Создаем ключ шифрования с использованием хэша
|
||||
const baseKey = config.ENCRYPTION_KEY;
|
||||
const combinedKey = baseKey + userIdStr;
|
||||
|
||||
// Создаем ключ и IV с использованием SHA-256
|
||||
const key = crypto.createHash('sha256')
|
||||
.update(config.ENCRYPTION_KEY + userIdStr)
|
||||
.digest();
|
||||
|
||||
const iv = crypto.randomBytes(16); // Генерируем случайный IV
|
||||
|
||||
// Создаем шифр
|
||||
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
||||
|
||||
// Шифруем мнемонику
|
||||
let encrypted = cipher.update(mnemonic, 'utf8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
|
||||
// Сохраняем зашифрованные данные вместе с IV
|
||||
const encryptedMnemonic = iv.toString('hex') + ':' + encrypted;
|
||||
|
||||
// Определяем путь деривации
|
||||
let derivationPath;
|
||||
if (walletType === 'USDT') {
|
||||
derivationPath = "m/44'/60'/0'/0/1"; // Путь для USDT
|
||||
} else if (walletType === 'USDC') {
|
||||
derivationPath = "m/44'/60'/0'/0/2"; // Путь для USDC
|
||||
} else {
|
||||
derivationPath = wallets[walletType.toUpperCase()].path;
|
||||
}
|
||||
|
||||
// Получаем адрес для базового типа
|
||||
const walletData = wallets[baseType.toUpperCase()];
|
||||
if (!walletData || !walletData.address) {
|
||||
console.error('Wallet generation failed:', {
|
||||
baseType,
|
||||
wallets: Object.keys(wallets),
|
||||
walletData
|
||||
});
|
||||
throw new Error('Failed to generate wallet address');
|
||||
}
|
||||
const address = walletData.address;
|
||||
|
||||
// Вставляем новый кошелек в базу данных
|
||||
await db.runAsync(
|
||||
`INSERT INTO crypto_wallets
|
||||
(user_id, wallet_type, address, derivation_path, mnemonic)
|
||||
VALUES (?, ?, ?, ?, ?)`,
|
||||
[userId, walletType, address, derivationPath, encryptedMnemonic]
|
||||
);
|
||||
|
||||
// Проверяем успешность вставки
|
||||
const insertedWallet = await db.getAsync(
|
||||
`SELECT * FROM crypto_wallets
|
||||
WHERE user_id = ? AND wallet_type = ?`,
|
||||
[userId, walletType]
|
||||
);
|
||||
|
||||
if (!insertedWallet) {
|
||||
throw new Error('Failed to verify wallet insertion');
|
||||
}
|
||||
|
||||
// Проверяем целостность записанной мнемоники
|
||||
// Разделяем IV и зашифрованные данные для проверки
|
||||
const [verify_ivHex, verify_encryptedData] = insertedWallet.mnemonic.split(':');
|
||||
const verify_iv = Buffer.from(verify_ivHex, 'hex');
|
||||
|
||||
// Создаем ключ для проверки
|
||||
const verify_key = crypto.createHash('sha256')
|
||||
.update(config.ENCRYPTION_KEY + userId)
|
||||
.digest();
|
||||
|
||||
// Создаем дешифратор для проверки
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', verify_key, verify_iv);
|
||||
|
||||
// Дешифруем данные
|
||||
let decryptedMnemonic;
|
||||
try {
|
||||
decryptedMnemonic = decipher.update(verify_encryptedData, 'hex', 'utf8');
|
||||
decryptedMnemonic += decipher.final('utf8');
|
||||
|
||||
if (!decryptedMnemonic) {
|
||||
throw new Error('Failed to decrypt mnemonic');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Decryption error:', error);
|
||||
throw new Error('Failed to decrypt mnemonic: ' + error.message);
|
||||
}
|
||||
|
||||
if (decryptedMnemonic !== mnemonic) {
|
||||
console.error('Mnemonic verification failed for wallet:', walletType);
|
||||
// Удаляем кошелек в случае ошибки
|
||||
await db.runAsync(
|
||||
`DELETE FROM crypto_wallets
|
||||
WHERE user_id = ? AND wallet_type = ?`,
|
||||
[userId, walletType]
|
||||
);
|
||||
throw new Error('Mnemonic verification failed');
|
||||
}
|
||||
|
||||
console.log(`Successfully created and verified wallet: ${walletType}`, {
|
||||
address,
|
||||
derivationPath,
|
||||
userId,
|
||||
walletType
|
||||
});
|
||||
return {
|
||||
address,
|
||||
derivationPath,
|
||||
userId,
|
||||
walletType
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error creating wallet:', error);
|
||||
throw new Error('Failed to create wallet: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async decryptMnemonic(encryptedMnemonic, userId) {
|
||||
try {
|
||||
// Проверяем наличие ключа шифрования
|
||||
if (!config.ENCRYPTION_KEY || typeof config.ENCRYPTION_KEY !== 'string') {
|
||||
throw new Error('Encryption key is not configured');
|
||||
}
|
||||
|
||||
// Разделяем IV и зашифрованные данные
|
||||
const [ivHex, encryptedData] = encryptedMnemonic.split(':');
|
||||
if (!ivHex || !encryptedData) {
|
||||
throw new Error('Invalid encrypted mnemonic format');
|
||||
}
|
||||
|
||||
// Создаем ключ дешифрования
|
||||
const key = crypto.createHash('sha256')
|
||||
.update(config.ENCRYPTION_KEY + userId.toString())
|
||||
.digest();
|
||||
|
||||
// Преобразуем IV из hex
|
||||
const iv = Buffer.from(ivHex, 'hex');
|
||||
|
||||
// Создаем дешифратор
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
||||
|
||||
// Дешифруем данные
|
||||
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
|
||||
return decrypted;
|
||||
} catch (error) {
|
||||
console.error('Error decrypting mnemonic:', error);
|
||||
throw new Error('Failed to decrypt mnemonic: ' + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default WalletService;
|
@ -7,6 +7,7 @@ import { publicToAddress } from 'ethereumjs-util';
|
||||
import * as bitcoin from 'bitcoinjs-lib';
|
||||
import * as ecc from 'tiny-secp256k1';
|
||||
import { ECPairFactory } from 'ecpair';
|
||||
import CryptoJS from 'crypto-js';
|
||||
|
||||
const ECPair = ECPairFactory(ecc);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user