- Создана форма деплоя TreasuryModule с детальными настройками казны - Создана форма деплоя TimelockModule с настройками временных задержек - Создана форма деплоя DLEReader с простой конфигурацией - Добавлены маршруты и индексы для всех модулей - Исправлены пути импорта BaseLayout - Добавлены авторские права во все файлы - Улучшена архитектура деплоя модулей отдельно от основного DLE
443 lines
14 KiB
JavaScript
443 lines
14 KiB
JavaScript
/**
|
||
* 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');
|
||
|
||
// Получить поддерживаемые сети
|
||
router.post('/get-supported-chains', 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)",
|
||
"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))
|
||
}
|
||
});
|
||
|
||
} catch (error) {
|
||
console.error('[DLE Multichain] Ошибка при получении поддерживаемых сетей:', error);
|
||
res.status(500).json({
|
||
success: false,
|
||
error: 'Ошибка при получении поддерживаемых сетей: ' + error.message
|
||
});
|
||
}
|
||
});
|
||
|
||
// Проверить поддержку сети
|
||
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;
|