Files
DLE/backend/routes/dleTokens.js
2025-10-30 22:41:04 +03:00

315 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) 2024-2025 Тарабанов Александр Викторович
* All rights reserved.
*
* This software is proprietary and confidential.
* Unauthorized copying, modification, or distribution is prohibited.
*
* For licensing inquiries: info@hb3-accelerator.com
* Website: https://hb3-accelerator.com
* GitHub: https://github.com/VC-HB3-Accelerator
*/
const express = require('express');
const router = express.Router();
const { ethers } = require('ethers');
const rpcProviderService = require('../services/rpcProviderService');
const { getSupportedChainIds } = require('../utils/networkLoader');
// Получить баланс токенов
router.post('/get-token-balance', async (req, res) => {
try {
const { dleAddress, account } = req.body;
if (!dleAddress || !account) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и адрес аккаунта обязательны'
});
}
console.log(`[DLE Tokens] Получение баланса токенов для аккаунта: ${account} в DLE: ${dleAddress}`);
// Определяем корректную сеть для данного адреса
let rpcUrl, targetChainId;
let candidateChainIds = []; // Будет заполнено из deploy_params
try {
// Получаем поддерживаемые сети из параметров деплоя
const latestParams = await deployParamsService.getLatestDeployParams(1);
if (latestParams.length > 0) {
const params = latestParams[0];
candidateChainIds = params.supportedChainIds || candidateChainIds;
}
} catch (error) {
console.error('❌ Ошибка получения параметров деплоя, используем fallback:', error);
}
for (const cid of candidateChainIds) {
try {
const url = await rpcProviderService.getRpcUrlByChainId(cid);
if (!url) continue;
const prov = new ethers.JsonRpcProvider(url);
const code = await prov.getCode(dleAddress);
if (code && code !== '0x') {
rpcUrl = url;
targetChainId = cid;
break;
}
} catch (_) {}
}
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'Не удалось найти сеть, где по адресу есть контракт'
});
}
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(await rpcProviderService.getRpcUrlByChainId(chainId));
const dleAbi = [
"function balanceOf(address account) external view returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем баланс токенов
const balance = await dle.balanceOf(account);
console.log(`[DLE Tokens] Баланс токенов для ${account}: ${balance}`);
res.json({
success: true,
data: {
account: account,
balance: ethers.formatUnits(balance, 18)
}
});
} catch (error) {
console.error('[DLE Tokens] Ошибка при получении баланса токенов:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении баланса токенов: ' + error.message
});
}
});
// Получить общее предложение токенов
router.post('/get-total-supply', async (req, res) => {
try {
const { dleAddress } = req.body;
if (!dleAddress) {
return res.status(400).json({
success: false,
error: 'Адрес DLE обязателен'
});
}
console.log(`[DLE Tokens] Получение общего предложения токенов для DLE: ${dleAddress}`);
// Определяем корректную сеть для данного адреса
let rpcUrl, targetChainId;
let candidateChainIds = []; // Будет заполнено из deploy_params
try {
// Получаем поддерживаемые сети из параметров деплоя
const latestParams = await deployParamsService.getLatestDeployParams(1);
if (latestParams.length > 0) {
const params = latestParams[0];
candidateChainIds = params.supportedChainIds || candidateChainIds;
}
} catch (error) {
console.error('❌ Ошибка получения параметров деплоя, используем fallback:', error);
}
for (const cid of candidateChainIds) {
try {
const url = await rpcProviderService.getRpcUrlByChainId(cid);
if (!url) continue;
const prov = new ethers.JsonRpcProvider(url);
const code = await prov.getCode(dleAddress);
if (code && code !== '0x') {
rpcUrl = url;
targetChainId = cid;
break;
}
} catch (_) {}
}
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'Не удалось найти сеть, где по адресу есть контракт'
});
}
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(await rpcProviderService.getRpcUrlByChainId(chainId));
const dleAbi = [
"function totalSupply() external view returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем общее предложение токенов
const totalSupply = await dle.totalSupply();
console.log(`[DLE Tokens] Общее предложение токенов: ${totalSupply}`);
res.json({
success: true,
data: {
totalSupply: ethers.formatUnits(totalSupply, 18)
}
});
} catch (error) {
console.error('[DLE Tokens] Ошибка при получении общего предложения токенов:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении общего предложения токенов: ' + error.message
});
}
});
// Получить держателей токенов
router.post('/get-token-holders', async (req, res) => {
try {
const { dleAddress, offset = 0, limit = 10 } = req.body;
if (!dleAddress) {
return res.status(400).json({
success: false,
error: 'Адрес DLE обязателен'
});
}
console.log(`[DLE Tokens] Получение держателей токенов для DLE: ${dleAddress}`);
// Определяем корректную сеть для данного адреса
let rpcUrl, targetChainId;
let candidateChainIds = []; // Будет заполнено из deploy_params
try {
// Получаем поддерживаемые сети из параметров деплоя
const latestParams = await deployParamsService.getLatestDeployParams(1);
if (latestParams.length > 0) {
const params = latestParams[0];
candidateChainIds = params.supportedChainIds || candidateChainIds;
}
} catch (error) {
console.error('❌ Ошибка получения параметров деплоя, используем fallback:', error);
}
for (const cid of candidateChainIds) {
try {
const url = await rpcProviderService.getRpcUrlByChainId(cid);
if (!url) continue;
const prov = new ethers.JsonRpcProvider(url);
const code = await prov.getCode(dleAddress);
if (code && code !== '0x') {
rpcUrl = url;
targetChainId = cid;
break;
}
} catch (_) {}
}
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'Не удалось найти сеть, где по адресу есть контракт'
});
}
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(await rpcProviderService.getRpcUrlByChainId(chainId));
const dleAbi = [
"function totalSupply() external view returns (uint256)",
"function balanceOf(address account) external view returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем общее предложение токенов
const totalSupply = await dle.totalSupply();
// Список известных адресов для проверки
const knownAddresses = [
"0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B", // Создатель
"0x15A4ed4759e5762174b300a4Cf51cc17ad967f4d", // Инициатор предложения
"0x2F2F070AA10bD3Ea14949b9953E2040a05421B17", // Сам DLE контракт
"0x0000000000000000000000000000000000000000" // Нулевой адрес
];
const holders = [];
// Проверяем балансы известных адресов
for (const address of knownAddresses) {
try {
const balance = await dle.balanceOf(address);
if (balance > 0) {
const percentage = (Number(balance) / Number(totalSupply)) * 100;
holders.push({
address: address,
balance: ethers.formatUnits(balance, 18),
percentage: percentage
});
}
} catch (error) {
console.log(`[DLE Tokens] Ошибка при получении баланса для ${address}:`, error.message);
}
}
// Сортируем по балансу (убывание)
holders.sort((a, b) => Number(b.balance) - Number(a.balance));
// Применяем пагинацию
const start = Number(offset);
const end = start + Number(limit);
const paginatedHolders = holders.slice(start, end);
console.log(`[DLE Tokens] Найдено держателей токенов: ${holders.length}`);
res.json({
success: true,
data: {
holders: paginatedHolders,
total: holders.length,
offset: Number(offset),
limit: Number(limit)
}
});
} catch (error) {
console.error('[DLE Tokens] Ошибка при получении держателей токенов:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении держателей токенов: ' + error.message
});
}
});
module.exports = router;