ваше сообщение коммита

This commit is contained in:
2025-09-30 00:23:37 +03:00
parent ca718e3178
commit 4b03951b31
77 changed files with 17161 additions and 7255 deletions

View File

@@ -1,442 +1,124 @@
/**
* 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/HB3-ACCELERATOR
*/
const express = require('express');
const router = express.Router();
const { ethers } = require('ethers');
const rpcProviderService = require('../services/rpcProviderService');
const deployParamsService = require('../services/deployParamsService');
// Получить поддерживаемые сети
router.post('/get-supported-chains', async (req, res) => {
/**
* Получить адрес контракта в указанной сети для мультичейн голосования
* POST /api/dle-core/get-multichain-contracts
*/
router.post('/get-multichain-contracts', async (req, res) => {
try {
const { dleAddress } = req.body;
const { originalContract, targetChainId } = req.body;
if (!dleAddress) {
console.log('🔍 [MULTICHAIN] Поиск контракта для мультичейн голосования:', {
originalContract,
targetChainId
});
if (!originalContract || !targetChainId) {
return res.status(400).json({
success: false,
error: 'Адрес DLE обязателен'
error: 'Не указан originalContract или targetChainId'
});
}
console.log(`[DLE Multichain] Получение поддерживаемых сетей для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
// Ищем контракт в указанной сети
// Для мультичейн контрактов с одинаковым адресом (детерминированный деплой)
// или контракты в разных сетях с разными адресами
// Сначала проверяем, есть ли контракт с таким же адресом в целевой сети
const contractsInTargetNetwork = await deployParamsService.getContractsByChainId(targetChainId);
console.log('📊 [MULTICHAIN] Контракты в целевой сети:', contractsInTargetNetwork);
// Ищем контракт в целевой сети (все контракты в targetChainId уже отфильтрованы)
const targetContract = contractsInTargetNetwork[0]; // Берем первый контракт в целевой сети
if (targetContract) {
console.log('✅ [MULTICHAIN] Найден контракт в целевой сети:', targetContract.dleAddress);
return res.json({
success: true,
contractAddress: targetContract.dleAddress,
chainId: targetChainId,
source: 'database'
});
}
// Если не найден контракт в целевой сети, проверяем мультичейн развертывание
// с одинаковым адресом (CREATE2)
const { ethers } = require('ethers');
// Получаем RPC URL из параметров деплоя
let rpcUrl;
try {
// Получаем последние параметры деплоя
const latestParams = await deployParamsService.getLatestDeployParams(1);
if (latestParams.length > 0) {
const params = latestParams[0];
const rpcUrls = params.rpcUrls || params.rpc_urls || {};
rpcUrl = rpcUrls[targetChainId];
}
// Если не найден в параметрах, используем fallback
if (!rpcUrl) {
const fallbackConfigs = {
'11155111': 'https://1rpc.io/sepolia',
'17000': 'https://ethereum-holesky.publicnode.com',
'421614': 'https://sepolia-rollup.arbitrum.io/rpc',
'84532': 'https://sepolia.base.org'
};
rpcUrl = fallbackConfigs[targetChainId];
}
if (!rpcUrl) {
return res.status(400).json({
success: false,
error: `Неподдерживаемая сеть: ${targetChainId}`
});
}
} catch (error) {
console.error('❌ Ошибка получения RPC URL:', error);
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
error: 'Ошибка получения конфигурации сети'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function getSupportedChainCount() external view returns (uint256)",
"function getSupportedChainId(uint256 _index) external view returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем количество поддерживаемых сетей
const chainCount = await dle.getSupportedChainCount();
// Получаем ID каждой сети
const supportedChains = [];
for (let i = 0; i < Number(chainCount); i++) {
const chainId = await dle.getSupportedChainId(i);
supportedChains.push(chainId);
}
console.log(`[DLE Multichain] Поддерживаемые сети:`, supportedChains);
res.json({
success: true,
data: {
chains: supportedChains.map(chainId => Number(chainId))
try {
const provider = new ethers.JsonRpcProvider(rpcUrl);
const contractCode = await provider.getCode(originalContract);
if (contractCode && contractCode !== '0x') {
console.log('✅ [MULTICHAIN] Контракт существует в целевой сети с тем же адресом (CREATE2)');
return res.json({
success: true,
contractAddress: originalContract,
chainId: targetChainId,
source: 'blockchain'
});
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при получении поддерживаемых сетей:', error);
res.status(500).json({
} catch (blockchainError) {
console.warn('⚠️ [MULTICHAIN] Ошибка проверки контракта в блокчейне:', blockchainError.message);
}
// Контракт не найден
console.log('❌ [MULTICHAIN] Контракт не найден в целевой сети');
return res.json({
success: false,
error: 'Ошибка при получении поддерживаемых сетей: ' + error.message
error: 'Контракт не найден в целевой сети'
});
} catch (error) {
console.error('❌ [MULTICHAIN] Ошибка поиска мультичейн контракта:', error);
return res.status(500).json({
success: false,
error: 'Внутренняя ошибка сервера'
});
}
});
// Проверить поддержку сети
router.post('/is-chain-supported', async (req, res) => {
try {
const { dleAddress, chainId } = req.body;
if (!dleAddress || chainId === undefined) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и ID сети обязательны'
});
}
console.log(`[DLE Multichain] Проверка поддержки сети ${chainId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function isChainSupported(uint256 _chainId) external view returns (bool)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Проверяем поддержку сети
const isSupported = await dle.isChainSupported(chainId);
console.log(`[DLE Multichain] Поддержка сети ${chainId}: ${isSupported}`);
res.json({
success: true,
data: {
chainId: Number(chainId),
isSupported: isSupported
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при проверке поддержки сети:', error);
res.status(500).json({
success: false,
error: 'Ошибка при проверке поддержки сети: ' + error.message
});
}
});
// Получить количество поддерживаемых сетей
router.post('/get-supported-chain-count', async (req, res) => {
try {
const { dleAddress } = req.body;
if (!dleAddress) {
return res.status(400).json({
success: false,
error: 'Адрес DLE обязателен'
});
}
console.log(`[DLE Multichain] Получение количества поддерживаемых сетей для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function getSupportedChainCount() external view returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем количество поддерживаемых сетей
const count = await dle.getSupportedChainCount();
console.log(`[DLE Multichain] Количество поддерживаемых сетей: ${count}`);
res.json({
success: true,
data: {
count: Number(count)
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при получении количества поддерживаемых сетей:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении количества поддерживаемых сетей: ' + error.message
});
}
});
// Получить ID сети по индексу
router.post('/get-supported-chain-id', async (req, res) => {
try {
const { dleAddress, index } = req.body;
if (!dleAddress || index === undefined) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и индекс обязательны'
});
}
console.log(`[DLE Multichain] Получение ID сети по индексу ${index} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function getSupportedChainId(uint256 _index) external view returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем ID сети по индексу
const chainId = await dle.getSupportedChainId(index);
console.log(`[DLE Multichain] ID сети по индексу ${index}: ${chainId}`);
res.json({
success: true,
data: {
index: Number(index),
chainId: Number(chainId)
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при получении ID сети по индексу:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении ID сети по индексу: ' + error.message
});
}
});
// Проверить подключение к сети
router.post('/check-chain-connection', async (req, res) => {
try {
const { dleAddress, chainId } = req.body;
if (!dleAddress || chainId === undefined) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и ID сети обязательны'
});
}
console.log(`[DLE Multichain] Проверка подключения к сети ${chainId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function checkChainConnection(uint256 _chainId) external view returns (bool)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Проверяем подключение к сети
const isAvailable = await dle.checkChainConnection(chainId);
console.log(`[DLE Multichain] Подключение к сети ${chainId}: ${isAvailable}`);
res.json({
success: true,
data: {
chainId: Number(chainId),
isAvailable: isAvailable
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при проверке подключения к сети:', error);
res.status(500).json({
success: false,
error: 'Ошибка при проверке подключения к сети: ' + error.message
});
}
});
// Проверить готовность к синхронизации
router.post('/check-sync-readiness', async (req, res) => {
try {
const { dleAddress, proposalId } = req.body;
if (!dleAddress || proposalId === undefined) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и ID предложения обязательны'
});
}
console.log(`[DLE Multichain] Проверка готовности к синхронизации предложения ${proposalId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function checkSyncReadiness(uint256 _proposalId) external view returns (bool)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Проверяем готовность к синхронизации
const allChainsReady = await dle.checkSyncReadiness(proposalId);
console.log(`[DLE Multichain] Готовность к синхронизации предложения ${proposalId}: ${allChainsReady}`);
res.json({
success: true,
data: {
proposalId: Number(proposalId),
allChainsReady: allChainsReady
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при проверке готовности к синхронизации:', error);
res.status(500).json({
success: false,
error: 'Ошибка при проверке готовности к синхронизации: ' + error.message
});
}
});
// Синхронизировать во все сети
router.post('/sync-to-all-chains', async (req, res) => {
try {
const { dleAddress, proposalId, userAddress, privateKey } = req.body;
if (!dleAddress || proposalId === undefined || !userAddress || !privateKey) {
return res.status(400).json({
success: false,
error: 'Все поля обязательны, включая приватный ключ'
});
}
console.log(`[DLE Multichain] Синхронизация предложения ${proposalId} во все сети для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const wallet = new ethers.Wallet(privateKey, provider);
const dleAbi = [
"function syncToAllChains(uint256 _proposalId) external"
];
const dle = new ethers.Contract(dleAddress, dleAbi, wallet);
// Синхронизируем во все сети
const tx = await dle.syncToAllChains(proposalId);
const receipt = await tx.wait();
console.log(`[DLE Multichain] Синхронизация выполнена:`, receipt);
res.json({
success: true,
data: {
transactionHash: receipt.hash
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при синхронизации во все сети:', error);
res.status(500).json({
success: false,
error: 'Ошибка при синхронизации во все сети: ' + error.message
});
}
});
// Исполнить предложение по подписям
router.post('/execute-proposal-by-signatures', async (req, res) => {
try {
const { dleAddress, proposalId, signatures, userAddress, privateKey } = req.body;
if (!dleAddress || proposalId === undefined || !signatures || !userAddress || !privateKey) {
return res.status(400).json({
success: false,
error: 'Все поля обязательны, включая приватный ключ'
});
}
console.log(`[DLE Multichain] Исполнение предложения ${proposalId} по подписям для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const wallet = new ethers.Wallet(privateKey, provider);
const dleAbi = [
"function executeProposalBySignatures(uint256 _proposalId, bytes[] calldata _signatures) external"
];
const dle = new ethers.Contract(dleAddress, dleAbi, wallet);
// Исполняем предложение по подписям
const tx = await dle.executeProposalBySignatures(proposalId, signatures);
const receipt = await tx.wait();
console.log(`[DLE Multichain] Предложение исполнено по подписям:`, receipt);
res.json({
success: true,
data: {
transactionHash: receipt.hash
}
});
} catch (error) {
console.error('[DLE Multichain] Ошибка при исполнении предложения по подписям:', error);
res.status(500).json({
success: false,
error: 'Ошибка при исполнении предложения по подписям: ' + error.message
});
}
});
module.exports = router;
module.exports = router;