crypto mnemonic case
This commit is contained in:
parent
24aebd0bcf
commit
fa09e81ddf
@ -2,5 +2,6 @@ export default {
|
|||||||
BOT_TOKEN: process.env.BOT_TOKEN,
|
BOT_TOKEN: process.env.BOT_TOKEN,
|
||||||
ADMIN_IDS: process.env.ADMIN_IDS.split(","),
|
ADMIN_IDS: process.env.ADMIN_IDS.split(","),
|
||||||
SUPPORT_LINK: process.env.SUPPORT_LINK,
|
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 {
|
return {
|
||||||
address: wallet.address,
|
address: wallet.address,
|
||||||
balance: balance.toFixed(8),
|
balance: balance.toFixed(8),
|
||||||
usdValue: usdValue.toFixed(2),
|
usdValue: usdValue.toFixed(2),
|
||||||
status: wallet.wallet_type.includes('_') ? 'Archived' : 'Active',
|
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: 'balance', title: 'Balance' },
|
||||||
{ id: 'usdValue', title: 'Value (USD)' },
|
{ id: 'usdValue', title: 'Value (USD)' },
|
||||||
{ id: 'status', title: 'Status' },
|
{ 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');
|
await db.runAsync('BEGIN TRANSACTION');
|
||||||
|
|
||||||
try {
|
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(
|
const existingWallet = await db.getAsync(
|
||||||
'SELECT id, address FROM crypto_wallets WHERE user_id = ? AND wallet_type = ?',
|
'SELECT id, address FROM crypto_wallets WHERE user_id = ? AND wallet_type = ?',
|
||||||
@ -397,24 +380,30 @@ export default class UserWalletsHandler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сохраняем новый кошелек
|
// Создаем новый кошелек с использованием WalletService
|
||||||
await db.runAsync(
|
const walletResult = await WalletService.createWallet(user.id, walletType);
|
||||||
`INSERT INTO crypto_wallets (
|
|
||||||
user_id, wallet_type, address, derivation_path, mnemonic
|
if (!walletResult || !walletResult.address) {
|
||||||
) VALUES (?, ?, ?, ?, ?)`,
|
console.error('Wallet creation failed:', {
|
||||||
[
|
error: walletResult,
|
||||||
user.id,
|
userId: user.id,
|
||||||
walletType, // Используем выбранный тип (USDT, USDC, ETH и т.д.)
|
walletType
|
||||||
wallets[baseType].address, // Адрес берется из базового типа
|
});
|
||||||
derivationPath, // Используем корректный путь деривации
|
throw new Error('Failed to generate wallet address');
|
||||||
mnemonic
|
}
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Получаем адрес для отображения
|
// Получаем адрес для отображения
|
||||||
const displayAddress = wallets[baseType].address;
|
const displayAddress = walletResult.address;
|
||||||
const network = this.getNetworkName(walletType);
|
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`;
|
let message = `✅ New wallet generated successfully!\n\n`;
|
||||||
message += `Type: ${walletType}\n`;
|
message += `Type: ${walletType}\n`;
|
||||||
message += `Network: ${network}\n`;
|
message += `Network: ${network}\n`;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
// walletService.js
|
// walletService.js
|
||||||
|
|
||||||
import db from "../config/database.js";
|
import db from "../config/database.js";
|
||||||
|
import config from "../config/config.js";
|
||||||
import WalletUtils from "../utils/walletUtils.js";
|
import WalletUtils from "../utils/walletUtils.js";
|
||||||
|
import WalletGenerator from "../utils/walletGenerator.js";
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
class WalletService {
|
class WalletService {
|
||||||
static async getArchivedWalletsCount(user) {
|
static async getArchivedWalletsCount(user) {
|
||||||
@ -119,6 +122,187 @@ class WalletService {
|
|||||||
throw new Error('Failed to fetch wallets by type');
|
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;
|
export default WalletService;
|
@ -7,6 +7,7 @@ import { publicToAddress } from 'ethereumjs-util';
|
|||||||
import * as bitcoin from 'bitcoinjs-lib';
|
import * as bitcoin from 'bitcoinjs-lib';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
import * as ecc from 'tiny-secp256k1';
|
||||||
import { ECPairFactory } from 'ecpair';
|
import { ECPairFactory } from 'ecpair';
|
||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
const ECPair = ECPairFactory(ecc);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user