Initial commit

This commit is contained in:
SoftUniq
2024-11-13 22:31:18 +00:00
commit abfa7b43af
21 changed files with 8368 additions and 0 deletions

24
src/utils/errorHandler.js Normal file
View File

@@ -0,0 +1,24 @@
export default class ErrorHandler {
static async handleError(bot, chatId, error, context) {
console.error(`Error in ${context}:`, error);
const errorMessage = process.env.NODE_ENV === 'development'
? `Error: ${error.message}`
: 'An error occurred. Please try again later.';
try {
await bot.sendMessage(chatId, errorMessage);
} catch (sendError) {
console.error('Error sending error message:', sendError);
}
}
static handlePollingError(error) {
if (error.code === 'ETELEGRAM') {
console.error('Telegram API Error:', error.message);
process.exit(1);
} else {
console.error('Polling error:', error);
}
}
}

22
src/utils/validators.js Normal file
View File

@@ -0,0 +1,22 @@
export default class Validators {
static isValidLocation(country, city, district) {
return Boolean(country && city && district);
}
static isValidProduct(product) {
return Boolean(
product.name &&
product.category &&
product.price &&
product.price > 0
);
}
static isValidQuantity(quantity, stock) {
return quantity > 0 && quantity <= stock;
}
static isValidBalance(balance) {
return balance >= 0;
}
}

View File

@@ -0,0 +1,148 @@
import bip39 from 'bip39';
import HDKey from 'hdkey';
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);
export default class WalletGenerator {
static async generateMnemonic() {
try {
return bip39.generateMnemonic(256); // 24 words for maximum security
} catch (error) {
console.error('Error generating mnemonic:', error);
throw new Error('Failed to generate mnemonic');
}
}
static async encryptMnemonic(mnemonic, userId) {
try {
const key = process.env.ENCRYPTION_KEY || 'default-key-12345';
return CryptoJS.AES.encrypt(mnemonic, key + userId.toString()).toString();
} catch (error) {
console.error('Error encrypting mnemonic:', error);
throw new Error('Failed to encrypt mnemonic');
}
}
static async decryptMnemonic(encryptedMnemonic, userId) {
try {
const key = process.env.ENCRYPTION_KEY || 'default-key-12345';
const bytes = CryptoJS.AES.decrypt(encryptedMnemonic, key + userId.toString());
return bytes.toString(CryptoJS.enc.Utf8);
} catch (error) {
console.error('Error decrypting mnemonic:', error);
throw new Error('Failed to decrypt mnemonic');
}
}
static async generateWallets(mnemonic) {
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 LTC wallet (BIP84 - Native SegWit)
const ltcNode = hdkey.derive("m/84'/2'/0'/0/0");
const ltcKeyPair = ECPair.fromPrivateKey(ltcNode.privateKey);
const ltcAddress = bitcoin.payments.p2wpkh({
pubkey: ltcKeyPair.publicKey,
network: {
messagePrefix: '\x19Litecoin Signed Message:\n',
bech32: 'ltc',
bip32: {
public: 0x019da462,
private: 0x019d9cfe
},
pubKeyHash: 0x30,
scriptHash: 0x32,
wif: 0xb0
}
}).address;
// Generate TRON address (BIP44)
const tronNode = hdkey.derive("m/44'/195'/0'/0/0");
const tronAddress = this.generateTronAddress(tronNode.publicKey);
return {
BTC: {
address: btcAddress,
path: "m/84'/0'/0'/0/0"
},
ETH: {
address: ethAddress,
path: "m/44'/60'/0'/0/0"
},
LTC: {
address: ltcAddress,
path: "m/84'/2'/0'/0/0"
},
TRON: {
address: tronAddress,
path: "m/44'/195'/0'/0/0"
}
};
} catch (error) {
console.error('Error in generateWallets:', error);
throw new Error('Failed to generate cryptocurrency wallets: ' + error.message);
}
}
static generateTronAddress(publicKey) {
try {
const addressPrefix = '41'; // TRON mainnet prefix
const pubKeyHash = CryptoJS.SHA256(
CryptoJS.lib.WordArray.create(publicKey)
).toString();
const address = addressPrefix + pubKeyHash.substring(0, 40);
return this.base58Encode(Buffer.from(address, 'hex'));
} catch (error) {
console.error('Error generating TRON address:', error);
throw new Error('Failed to generate TRON address: ' + error.message);
}
}
static base58Encode(buffer) {
try {
const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
let digits = [0];
for (let i = 0; i < buffer.length; i++) {
let carry = buffer[i];
for (let j = 0; j < digits.length; j++) {
carry += digits[j] << 8;
digits[j] = carry % 58;
carry = (carry / 58) | 0;
}
while (carry > 0) {
digits.push(carry % 58);
carry = (carry / 58) | 0;
}
}
// Add leading zeros
for (let i = 0; buffer[i] === 0 && i < buffer.length - 1; i++) {
digits.push(0);
}
return digits.reverse().map(digit => ALPHABET[digit]).join('');
} catch (error) {
console.error('Error in base58Encode:', error);
throw new Error('Failed to encode address: ' + error.message);
}
}
}

164
src/utils/walletService.js Normal file
View File

@@ -0,0 +1,164 @@
import axios from 'axios';
export default class WalletService {
constructor(btcAddress, ltcAddress, trxAddress, ethAddress, userId, minTimestamp) {
this.btcAddress = btcAddress;
this.ltcAddress = ltcAddress;
this.trxAddress = trxAddress;
this.ethAddress = ethAddress;
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');
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
};
} catch (error) {
console.error('Error fetching crypto prices:', error);
return {
btc: 0, ltc: 0, eth: 0, usdt: 1, usdc: 1, trx: 0, usdd: 1
};
}
}
async fetchApiRequest(url) {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
return null;
}
}
async getBtcBalance() {
if (!this.btcAddress) return 0;
try {
const url = `https://blockchain.info/balance?active=${this.btcAddress}`;
const data = await this.fetchApiRequest(url);
return data?.[this.btcAddress]?.final_balance / 100000000 || 0;
} catch (error) {
console.error('Error getting BTC balance:', error);
return 0;
}
}
async getLtcBalance() {
if (!this.ltcAddress) return 0;
try {
const url = `https://api.blockcypher.com/v1/ltc/main/addrs/${this.ltcAddress}/balance`;
const data = await this.fetchApiRequest(url);
return data?.balance / 100000000 || 0;
} catch (error) {
console.error('Error getting LTC balance:', error);
return 0;
}
}
async getEthBalance() {
if (!this.ethAddress) return 0;
try {
const url = `https://api.etherscan.io/api?module=account&action=balance&address=${this.ethAddress}&tag=latest`;
const data = await this.fetchApiRequest(url);
return data?.result ? parseFloat(data.result) / 1e18 : 0;
} catch (error) {
console.error('Error getting ETH balance:', error);
return 0;
}
}
async getUsdtErc20Balance() {
if (!this.ethAddress) return 0;
try {
const url = `https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=0xdac17f958d2ee523a2206206994597c13d831ec7&address=${this.ethAddress}&tag=latest`;
const data = await this.fetchApiRequest(url);
return data?.result ? parseFloat(data.result) / 1e6 : 0;
} catch (error) {
console.error('Error getting USDT ERC20 balance:', error);
return 0;
}
}
async getUsdcErc20Balance() {
if (!this.ethAddress) return 0;
try {
const url = `https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&address=${this.ethAddress}&tag=latest`;
const data = await this.fetchApiRequest(url);
return data?.result ? parseFloat(data.result) / 1e6 : 0;
} catch (error) {
console.error('Error getting USDC ERC20 balance:', error);
return 0;
}
}
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,
ltcBalance,
ethBalance,
usdtErc20Balance,
usdcErc20Balance,
usdtTrc20Balance,
usddTrc20Balance,
prices
] = await Promise.all([
this.getBtcBalance(),
this.getLtcBalance(),
this.getEthBalance(),
this.getUsdtErc20Balance(),
this.getUsdcErc20Balance(),
this.getUsdtTrc20Balance(),
this.getUsddTrc20Balance(),
WalletService.getCryptoPrices()
]);
return {
BTC: { amount: btcBalance, usdValue: btcBalance * prices.btc },
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 }
};
}
}