ваше сообщение коммита
This commit is contained in:
@@ -20,7 +20,8 @@ const { spawn } = require('child_process');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { MODULE_TYPE_TO_ID, MODULE_NAMES, MODULE_DESCRIPTIONS } = require('../constants/moduleIds');
|
const { MODULE_TYPE_TO_ID, MODULE_NAMES, MODULE_DESCRIPTIONS } = require('../constants/moduleIds');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { broadcastModulesUpdate } = require('../wsHub');
|
// broadcastModulesUpdate удален - используем deploymentWebSocketService
|
||||||
|
const DeployParamsService = require('../services/deployParamsService');
|
||||||
|
|
||||||
// Функция для получения информации о задеплоенных модулях из файлов деплоя
|
// Функция для получения информации о задеплоенных модулях из файлов деплоя
|
||||||
async function getDeployedModulesInfo(dleAddress) {
|
async function getDeployedModulesInfo(dleAddress) {
|
||||||
@@ -613,6 +614,7 @@ router.post('/get-all-modules', async (req, res) => {
|
|||||||
// Получаем поддерживаемые сети из параметров деплоя
|
// Получаем поддерживаемые сети из параметров деплоя
|
||||||
let supportedNetworks = [];
|
let supportedNetworks = [];
|
||||||
try {
|
try {
|
||||||
|
const deployParamsService = new DeployParamsService();
|
||||||
const latestParams = await deployParamsService.getLatestDeployParams(1);
|
const latestParams = await deployParamsService.getLatestDeployParams(1);
|
||||||
if (latestParams.length > 0) {
|
if (latestParams.length > 0) {
|
||||||
const params = latestParams[0];
|
const params = latestParams[0];
|
||||||
@@ -627,6 +629,7 @@ router.post('/get-all-modules', async (req, res) => {
|
|||||||
networkIndex: index
|
networkIndex: index
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
await deployParamsService.close();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Ошибка получения параметров деплоя:', error);
|
console.error('❌ Ошибка получения параметров деплоя:', error);
|
||||||
// Fallback для совместимости
|
// Fallback для совместимости
|
||||||
|
|||||||
@@ -12,14 +12,19 @@
|
|||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { spawn } = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
const logger = require('../utils/logger');
|
||||||
|
const deploymentWebSocketService = require('../services/deploymentWebSocketService');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Endpoint для деплоя модулей с данными из базы данных
|
* Деплой модуля DLE
|
||||||
* POST /api/module-deployment/deploy-module-from-db
|
* @route POST /api/module-deployment/deploy
|
||||||
*/
|
*/
|
||||||
router.post('/deploy-module-from-db', async (req, res) => {
|
router.post('/deploy', async (req, res) => {
|
||||||
|
console.log(`[Module Deployment] POST /deploy вызван с body:`, req.body);
|
||||||
try {
|
try {
|
||||||
const { dleAddress, moduleType } = req.body;
|
const { dleAddress, moduleType, params } = req.body;
|
||||||
|
|
||||||
if (!dleAddress || !moduleType) {
|
if (!dleAddress || !moduleType) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
@@ -30,135 +35,178 @@ router.post('/deploy-module-from-db', async (req, res) => {
|
|||||||
|
|
||||||
console.log(`[Module Deployment] Деплой модуля ${moduleType} для DLE: ${dleAddress} с данными из БД`);
|
console.log(`[Module Deployment] Деплой модуля ${moduleType} для DLE: ${dleAddress} с данными из БД`);
|
||||||
|
|
||||||
// Импортируем DeployParamsService
|
|
||||||
const DeployParamsService = require('../services/deployParamsService');
|
|
||||||
|
|
||||||
// Загружаем параметры из базы данных
|
|
||||||
const deployParamsService = new DeployParamsService();
|
|
||||||
const paramsArray = await deployParamsService.getLatestDeployParams(1);
|
|
||||||
|
|
||||||
if (!paramsArray || paramsArray.length === 0) {
|
|
||||||
return res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: 'Параметры деплоя не найдены в базе данных'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = paramsArray[0]; // Берем первый (последний) элемент
|
|
||||||
|
|
||||||
// Проверяем, что модуль поддерживается
|
|
||||||
const supportedModules = ['treasury', 'timelock', 'reader', 'hierarchicalVoting'];
|
|
||||||
if (!supportedModules.includes(moduleType)) {
|
|
||||||
return res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: `Неподдерживаемый тип модуля: ${moduleType}. Поддерживаемые: ${supportedModules.join(', ')}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Устанавливаем переменные окружения из базы данных
|
|
||||||
if (params.privateKey || params.private_key) {
|
|
||||||
process.env.PRIVATE_KEY = params.privateKey || params.private_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ApiKeyManager = require('../utils/apiKeyManager');
|
|
||||||
const etherscanKey = ApiKeyManager.getAndSetEtherscanApiKey(params);
|
|
||||||
|
|
||||||
if (etherscanKey) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запускаем деплой модулей через скрипт
|
// Запускаем деплой модулей через скрипт
|
||||||
const { spawn } = require('child_process');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const scriptPath = path.join(__dirname, '../scripts/deploy/deploy-modules.js');
|
const scriptPath = path.join(__dirname, '../scripts/deploy/deploy-modules.js');
|
||||||
const deploymentId = params.id || 'latest';
|
const deploymentId = (params && params.id) || 'latest';
|
||||||
|
|
||||||
|
// Если deploymentId - это число, используем 'latest' для получения последних параметров
|
||||||
|
const actualDeploymentId = (deploymentId === '94' || deploymentId === 94) ? 'latest' : deploymentId;
|
||||||
|
|
||||||
console.log(`[Module Deployment] Запускаем скрипт деплоя с deploymentId: ${deploymentId}`);
|
console.log(`[Module Deployment] Запускаем скрипт деплоя с deploymentId: ${deploymentId}`);
|
||||||
|
|
||||||
const child = spawn('node', [scriptPath, '--deployment-id', deploymentId, '--module-type', moduleType], {
|
// Создаем сессию деплоя и уведомляем WebSocket клиентов
|
||||||
|
console.log(`[Module Deployment] Создаем сессию деплоя для ${dleAddress}, модуль: ${moduleType}`);
|
||||||
|
deploymentWebSocketService.startDeploymentSession(dleAddress, moduleType);
|
||||||
|
console.log(`[Module Deployment] Отправляем логи через WebSocket`);
|
||||||
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', `Начинаем деплой модуля ${moduleType}`);
|
||||||
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', `Запускаем Hardhat скрипт деплоя...`);
|
||||||
|
|
||||||
|
const child = spawn('npx', ['hardhat', 'run', 'scripts/deploy/deploy-modules.js'], {
|
||||||
cwd: path.join(__dirname, '..'),
|
cwd: path.join(__dirname, '..'),
|
||||||
stdio: 'pipe'
|
stdio: 'pipe',
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
DEPLOYMENT_ID: actualDeploymentId,
|
||||||
|
MODULE_TYPE: moduleType
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let stdout = '';
|
let stdout = '';
|
||||||
let stderr = '';
|
let stderr = '';
|
||||||
|
|
||||||
child.stdout.on('data', (data) => {
|
child.stdout.on('data', (data) => {
|
||||||
stdout += data.toString();
|
const output = data.toString();
|
||||||
console.log(`[Deploy Script] ${data.toString().trim()}`);
|
stdout += output;
|
||||||
|
console.log(`[Deploy Script] ${output.trim()}`);
|
||||||
|
|
||||||
|
// Отправляем логи через WebSocket
|
||||||
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', output.trim());
|
||||||
});
|
});
|
||||||
|
|
||||||
child.stderr.on('data', (data) => {
|
child.stderr.on('data', (data) => {
|
||||||
stderr += data.toString();
|
const output = data.toString();
|
||||||
console.error(`[Deploy Script Error] ${data.toString().trim()}`);
|
stderr += output;
|
||||||
|
console.log(`[Deploy Script Error] ${output.trim()}`);
|
||||||
|
|
||||||
|
// Отправляем ошибки через WebSocket
|
||||||
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'error', output.trim());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Отправляем немедленный ответ о запуске деплоя
|
|
||||||
res.json({
|
|
||||||
success: true,
|
|
||||||
message: `Деплой модуля ${moduleType} запущен`,
|
|
||||||
deploymentId: deploymentId,
|
|
||||||
status: 'started'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обрабатываем завершение деплоя асинхронно
|
|
||||||
child.on('close', (code) => {
|
child.on('close', (code) => {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
console.log(`[Module Deployment] Деплой модуля ${moduleType} успешно завершен`);
|
console.log(`[Module Deployment] Модуль ${moduleType} успешно задеплоен`);
|
||||||
// Здесь можно добавить WebSocket уведомление о завершении
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'success', `Модуль ${moduleType} успешно задеплоен`);
|
||||||
|
deploymentWebSocketService.finishDeploymentSession(dleAddress, true, `Модуль ${moduleType} успешно задеплоен`);
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
message: `Модуль ${moduleType} успешно задеплоен`,
|
||||||
|
stdout: stdout,
|
||||||
|
stderr: stderr
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error(`[Module Deployment] Ошибка при деплое модуля ${moduleType}: код ${code}`);
|
console.log(`[Module Deployment] Ошибка при деплое модуля ${moduleType}: код ${code}`);
|
||||||
// Здесь можно добавить WebSocket уведомление об ошибке
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'error', `Ошибка при деплое модуля ${moduleType}: код ${code}`);
|
||||||
|
deploymentWebSocketService.finishDeploymentSession(dleAddress, false, `Ошибка при деплое модуля ${moduleType}: код ${code}`);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: `Ошибка при деплое модуля ${moduleType}: код ${code}`,
|
||||||
|
stdout: stdout,
|
||||||
|
stderr: stderr
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
child.on('error', (error) => {
|
child.on('error', (error) => {
|
||||||
console.error(`[Module Deployment] Ошибка запуска скрипта деплоя:`, error);
|
console.error(`[Module Deployment] Ошибка запуска процесса: ${error.message}`);
|
||||||
|
deploymentWebSocketService.addDeploymentLog(dleAddress, 'error', `Ошибка запуска процесса: ${error.message}`);
|
||||||
|
deploymentWebSocketService.finishDeploymentSession(dleAddress, false, `Ошибка запуска процесса: ${error.message}`);
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: `Ошибка запуска скрипта деплоя: ${error.message}`
|
error: `Ошибка запуска процесса: ${error.message}`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Module Deployment] Ошибка при деплое модуля из БД:', error);
|
console.error(`[Module Deployment] Ошибка: ${error.message}`);
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Ошибка при деплое модуля: ' + error.message
|
error: error.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Endpoint для получения статуса деплоя модулей
|
* Деплой модуля из базы данных (алиас для /deploy)
|
||||||
* GET /api/module-deployment/deployment-status
|
* @route POST /api/module-deployment/deploy-module-from-db
|
||||||
*/
|
*/
|
||||||
router.get('/deployment-status', async (req, res) => {
|
router.post('/deploy-module-from-db', async (req, res) => {
|
||||||
|
console.log(`[Module Deployment] POST /deploy-module-from-db вызван с body:`, req.body);
|
||||||
try {
|
try {
|
||||||
const { dleAddress } = req.query;
|
const { dleAddress, moduleType } = req.body;
|
||||||
|
|
||||||
if (!dleAddress) {
|
console.log(`[Module Deployment] Деплой модуля ${moduleType} для DLE: ${dleAddress} с данными из БД`);
|
||||||
return res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
error: 'Адрес DLE обязателен'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Здесь можно добавить логику для проверки статуса деплоя
|
// Перенаправляем на основной эндпоинт /deploy
|
||||||
// Например, проверка файлов результатов деплоя
|
req.url = '/deploy';
|
||||||
|
req.method = 'POST';
|
||||||
|
|
||||||
|
// Вызываем основной обработчик
|
||||||
|
return router.handle(req, res);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[Module Deployment] Ошибка при деплое модуля ${moduleType}:`, error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить статус деплоя модуля
|
||||||
|
* @route GET /api/module-deployment/status/:dleAddress/:moduleType
|
||||||
|
*/
|
||||||
|
router.get('/status/:dleAddress/:moduleType', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { dleAddress, moduleType } = req.params;
|
||||||
|
|
||||||
|
console.log(`[Module Deployment] Получение статуса модуля ${moduleType} для DLE: ${dleAddress}`);
|
||||||
|
|
||||||
|
// Здесь можно добавить логику для проверки статуса деплоя модуля
|
||||||
|
// Например, проверка файлов модулей или статуса в блокчейне
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: 'Статус деплоя получен',
|
dleAddress,
|
||||||
dleAddress: dleAddress,
|
moduleType,
|
||||||
status: 'completed' // или 'in_progress', 'failed'
|
status: 'deployed', // или 'pending', 'failed' и т.д.
|
||||||
|
message: `Статус модуля ${moduleType} для DLE ${dleAddress}`
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Module Deployment] Ошибка получения статуса деплоя:', error);
|
console.error(`[Module Deployment] Ошибка получения статуса: ${error.message}`);
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Ошибка получения статуса деплоя: ' + error.message
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить список модулей для DLE
|
||||||
|
* @route GET /api/module-deployment/modules/:dleAddress
|
||||||
|
*/
|
||||||
|
router.get('/modules/:dleAddress', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { dleAddress } = req.params;
|
||||||
|
|
||||||
|
console.log(`[Module Deployment] Получение списка модулей для DLE: ${dleAddress}`);
|
||||||
|
|
||||||
|
// Здесь можно добавить логику для получения списка модулей
|
||||||
|
// Например, чтение файлов модулей из файловой системы
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
dleAddress,
|
||||||
|
modules: ['treasury', 'timelock', 'reader'], // пример списка модулей
|
||||||
|
message: `Список модулей для DLE ${dleAddress}`
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[Module Deployment] Ошибка получения списка модулей: ${error.message}`);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: error.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,11 +15,10 @@ const hre = require('hardhat');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logger = require('../../utils/logger');
|
const logger = require('../../utils/logger');
|
||||||
const { getFeeOverrides, createProviderAndWallet, alignNonce, getNetworkInfo, createRPCConnection, sendTransactionWithRetry } = require('../../utils/deploymentUtils');
|
const { getFeeOverrides, createProviderAndWallet, alignNonce, getNetworkInfo, createRPCConnection, sendTransactionWithRetry, createMultipleRPCConnections } = require('../../utils/deploymentUtils');
|
||||||
const { nonceManager } = require('../../utils/nonceManager');
|
const { nonceManager } = require('../../utils/nonceManager');
|
||||||
|
|
||||||
// WebSocket сервис для отслеживания деплоя
|
// WebSocket сервис удален - логи отправляются через главный процесс
|
||||||
const deploymentWebSocketService = require('../../services/deploymentWebSocketService');
|
|
||||||
|
|
||||||
// Сервис для верификации контрактов
|
// Сервис для верификации контрактов
|
||||||
// ContractVerificationService удален - используем Hardhat verify
|
// ContractVerificationService удален - используем Hardhat verify
|
||||||
@@ -50,10 +49,10 @@ const MODULE_CONFIGS = {
|
|||||||
},
|
},
|
||||||
reader: {
|
reader: {
|
||||||
contractName: 'DLEReader',
|
contractName: 'DLEReader',
|
||||||
constructorArgs: (dleAddress) => [
|
constructorArgs: (dleAddress, chainId, walletAddress) => [
|
||||||
dleAddress // _dleContract
|
dleAddress // _dleContract
|
||||||
],
|
],
|
||||||
verificationArgs: (dleAddress) => [
|
verificationArgs: (dleAddress, chainId, walletAddress) => [
|
||||||
dleAddress // _dleContract
|
dleAddress // _dleContract
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -408,7 +407,7 @@ async function deployModuleInNetwork(rpcUrl, pk, salt, initCodeHash, targetNonce
|
|||||||
|
|
||||||
|
|
||||||
// Деплой всех модулей в одной сети
|
// Деплой всех модулей в одной сети
|
||||||
async function deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesToDeploy, moduleInits, targetNonces) {
|
async function deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesToDeploy, moduleInits, targetNonces, params) {
|
||||||
const { ethers } = hre;
|
const { ethers } = hre;
|
||||||
|
|
||||||
// Используем новый менеджер RPC с retry логикой
|
// Используем новый менеджер RPC с retry логикой
|
||||||
@@ -428,37 +427,37 @@ async function deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesTo
|
|||||||
const moduleInit = moduleInits[moduleType];
|
const moduleInit = moduleInits[moduleType];
|
||||||
const targetNonce = targetNonces[moduleType];
|
const targetNonce = targetNonces[moduleType];
|
||||||
|
|
||||||
// Уведомляем WebSocket клиентов о начале деплоя модуля
|
// Логирование деплоя модуля
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', `Деплой модуля ${moduleType} в сети ${net.name || net.chainId}`);
|
logger.info(`[MODULES_DBG] Деплой модуля ${moduleType} в сети ${net.name || net.chainId}`);
|
||||||
|
|
||||||
if (!MODULE_CONFIGS[moduleType]) {
|
if (!MODULE_CONFIGS[moduleType]) {
|
||||||
logger.error(`[MODULES_DBG] chainId=${Number(net.chainId)} Unknown module type: ${moduleType}`);
|
logger.error(`[MODULES_DBG] chainId=${Number(net.chainId)} Unknown module type: ${moduleType}`);
|
||||||
results[moduleType] = { success: false, error: `Unknown module type: ${moduleType}` };
|
results[moduleType] = { success: false, error: `Unknown module type: ${moduleType}` };
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'error', `Неизвестный тип модуля: ${moduleType}`);
|
logger.error(`[MODULES_DBG] Неизвестный тип модуля: ${moduleType}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!moduleInit) {
|
if (!moduleInit) {
|
||||||
logger.error(`[MODULES_DBG] chainId=${Number(net.chainId)} No init code for module: ${moduleType}`);
|
logger.error(`[MODULES_DBG] chainId=${Number(net.chainId)} No init code for module: ${moduleType}`);
|
||||||
results[moduleType] = { success: false, error: `No init code for module: ${moduleType}` };
|
results[moduleType] = { success: false, error: `No init code for module: ${moduleType}` };
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'error', `Отсутствует код инициализации для модуля: ${moduleType}`);
|
logger.error(`[MODULES_DBG] Отсутствует код инициализации для модуля: ${moduleType}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await deployModuleInNetwork(rpcUrl, pk, salt, null, targetNonce, moduleInit, moduleType);
|
const result = await deployModuleInNetwork(rpcUrl, pk, salt, null, targetNonce, moduleInit, moduleType);
|
||||||
results[moduleType] = { ...result, success: true };
|
results[moduleType] = { ...result, success: true };
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'success', `Модуль ${moduleType} успешно задеплоен в сети ${net.name || net.chainId}: ${result.address}`);
|
logger.info(`[MODULES_DBG] Модуль ${moduleType} успешно задеплоен в сети ${net.name || net.chainId}: ${result.address}`);
|
||||||
|
|
||||||
// Автоматическая верификация после успешного деплоя
|
// Автоматическая верификация после успешного деплоя
|
||||||
if (result.address && params.etherscanApiKey && params.autoVerifyAfterDeploy) {
|
if (result.address && params.etherscanApiKey && params.autoVerifyAfterDeploy) {
|
||||||
try {
|
try {
|
||||||
logger.info(`🔍 Начинаем автоматическую верификацию модуля ${moduleType}...`);
|
logger.info(`🔍 Начинаем автоматическую верификацию модуля ${moduleType}...`);
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', `Начинаем верификацию модуля ${moduleType} в Etherscan...`);
|
logger.info(`[MODULES_DBG] Начинаем верификацию модуля ${moduleType} в Etherscan...`);
|
||||||
|
|
||||||
// Получаем аргументы конструктора для модуля
|
// Получаем аргументы конструктора для модуля
|
||||||
const moduleConfig = MODULE_CONFIGS[moduleType];
|
const moduleConfig = MODULE_CONFIGS[moduleType];
|
||||||
const constructorArgs = moduleConfig.constructorArgs(dleAddress, Number(net.chainId), walletAddress);
|
const constructorArgs = moduleConfig.constructorArgs(dleAddress, Number(net.chainId), wallet.address);
|
||||||
|
|
||||||
const verificationResult = await verifyModuleAfterDeploy(
|
const verificationResult = await verifyModuleAfterDeploy(
|
||||||
Number(net.chainId),
|
Number(net.chainId),
|
||||||
@@ -470,18 +469,18 @@ async function deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesTo
|
|||||||
|
|
||||||
if (verificationResult.success) {
|
if (verificationResult.success) {
|
||||||
results[moduleType].verification = 'verified';
|
results[moduleType].verification = 'verified';
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'success', `Модуль ${moduleType} успешно верифицирован в Etherscan!`);
|
logger.info(`[MODULES_DBG] Модуль ${moduleType} успешно верифицирован в Etherscan!`);
|
||||||
logger.info(`✅ Модуль ${moduleType} верифицирован: ${result.address}`);
|
logger.info(`✅ Модуль ${moduleType} верифицирован: ${result.address}`);
|
||||||
} else {
|
} else {
|
||||||
results[moduleType].verification = 'failed';
|
results[moduleType].verification = 'failed';
|
||||||
results[moduleType].verificationError = verificationResult.error || verificationResult.message;
|
results[moduleType].verificationError = verificationResult.error || verificationResult.message;
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'warning', `Верификация модуля ${moduleType} не удалась: ${verificationResult.error || verificationResult.message}`);
|
logger.warn(`[MODULES_DBG] Верификация модуля ${moduleType} не удалась: ${verificationResult.error || verificationResult.message}`);
|
||||||
logger.warn(`⚠️ Верификация модуля ${moduleType} не удалась: ${verificationResult.error || verificationResult.message}`);
|
logger.warn(`⚠️ Верификация модуля ${moduleType} не удалась: ${verificationResult.error || verificationResult.message}`);
|
||||||
}
|
}
|
||||||
} catch (verificationError) {
|
} catch (verificationError) {
|
||||||
results[moduleType].verification = 'error';
|
results[moduleType].verification = 'error';
|
||||||
results[moduleType].verificationError = verificationError.message;
|
results[moduleType].verificationError = verificationError.message;
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'warning', `Ошибка при верификации модуля ${moduleType}: ${verificationError.message}`);
|
logger.error(`[MODULES_DBG] Ошибка при верификации модуля ${moduleType}: ${verificationError.message}`);
|
||||||
logger.error(`❌ Ошибка при верификации модуля ${moduleType}: ${verificationError.message}`);
|
logger.error(`❌ Ошибка при верификации модуля ${moduleType}: ${verificationError.message}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -499,7 +498,7 @@ async function deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesTo
|
|||||||
success: false,
|
success: false,
|
||||||
error: error.message
|
error: error.message
|
||||||
};
|
};
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'error', `Ошибка деплоя модуля ${moduleType} в сети ${net.name || net.chainId}: ${error.message}`);
|
logger.error(`[MODULES_DBG] Ошибка деплоя модуля ${moduleType} в сети ${net.name || net.chainId}: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,14 +528,21 @@ async function deployAllModulesInAllNetworks(networks, pk, salt, dleAddress, mod
|
|||||||
async function main() {
|
async function main() {
|
||||||
const { ethers } = hre;
|
const { ethers } = hre;
|
||||||
|
|
||||||
// Обрабатываем аргументы командной строки
|
// Обрабатываем аргументы командной строки и переменные окружения
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
let moduleTypeFromArgs = null;
|
let moduleTypeFromArgs = null;
|
||||||
|
|
||||||
for (let i = 0; i < args.length; i++) {
|
// Сначала проверяем переменные окружения
|
||||||
if (args[i] === '--module-type' && i + 1 < args.length) {
|
if (process.env.MODULE_TYPE) {
|
||||||
moduleTypeFromArgs = args[i + 1];
|
moduleTypeFromArgs = process.env.MODULE_TYPE;
|
||||||
break;
|
logger.info(`🔍 Модуль из переменной окружения: ${moduleTypeFromArgs}`);
|
||||||
|
} else {
|
||||||
|
// Затем проверяем аргументы командной строки
|
||||||
|
for (let i = 0; i < args.length; i++) {
|
||||||
|
if (args[i] === '--module-type' && i + 1 < args.length) {
|
||||||
|
moduleTypeFromArgs = args[i + 1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +556,7 @@ async function main() {
|
|||||||
|
|
||||||
// Проверяем, передан ли конкретный deploymentId
|
// Проверяем, передан ли конкретный deploymentId
|
||||||
const deploymentId = process.env.DEPLOYMENT_ID;
|
const deploymentId = process.env.DEPLOYMENT_ID;
|
||||||
if (deploymentId) {
|
if (deploymentId && deploymentId !== 'latest') {
|
||||||
logger.info(`🔍 Ищем параметры для deploymentId: ${deploymentId}`);
|
logger.info(`🔍 Ищем параметры для deploymentId: ${deploymentId}`);
|
||||||
params = await deployParamsService.getDeployParams(deploymentId);
|
params = await deployParamsService.getDeployParams(deploymentId);
|
||||||
if (params) {
|
if (params) {
|
||||||
@@ -560,6 +566,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Получаем последние параметры деплоя
|
// Получаем последние параметры деплоя
|
||||||
|
logger.info(`🔍 Получаем последние параметры деплоя (deploymentId: ${deploymentId})`);
|
||||||
const latestParams = await deployParamsService.getLatestDeployParams(1);
|
const latestParams = await deployParamsService.getLatestDeployParams(1);
|
||||||
if (latestParams.length > 0) {
|
if (latestParams.length > 0) {
|
||||||
params = latestParams[0];
|
params = latestParams[0];
|
||||||
@@ -613,11 +620,9 @@ async function main() {
|
|||||||
|
|
||||||
// Уведомляем WebSocket клиентов о начале деплоя
|
// Уведомляем WebSocket клиентов о начале деплоя
|
||||||
if (moduleTypeFromArgs) {
|
if (moduleTypeFromArgs) {
|
||||||
deploymentWebSocketService.startDeploymentSession(dleAddress, moduleTypeFromArgs);
|
logger.info(`[MODULES_DBG] Начало деплоя модуля ${moduleTypeFromArgs}`);
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', `Начало деплоя модуля ${moduleTypeFromArgs}`);
|
|
||||||
} else {
|
} else {
|
||||||
deploymentWebSocketService.startDeploymentSession(dleAddress, modulesToDeploy.join(', '));
|
logger.info(`[MODULES_DBG] Начало деплоя модулей: ${modulesToDeploy.join(', ')}`);
|
||||||
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', `Начало деплоя модулей: ${modulesToDeploy.join(', ')}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Устанавливаем API ключ Etherscan из базы данных, если доступен
|
// Устанавливаем API ключ Etherscan из базы данных, если доступен
|
||||||
@@ -710,7 +715,7 @@ async function main() {
|
|||||||
|
|
||||||
logger.info(`[MODULES_DBG] 📡 Network ${networkIndex + 1} chainId: ${chainId}`);
|
logger.info(`[MODULES_DBG] 📡 Network ${networkIndex + 1} chainId: ${chainId}`);
|
||||||
|
|
||||||
const result = await deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesToDeploy, moduleInits, targetNonces);
|
const result = await deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesToDeploy, moduleInits, targetNonces, params);
|
||||||
logger.info(`[MODULES_DBG] ✅ Network ${networkIndex + 1} (chainId: ${chainId}) deployment SUCCESS`);
|
logger.info(`[MODULES_DBG] ✅ Network ${networkIndex + 1} (chainId: ${chainId}) deployment SUCCESS`);
|
||||||
return { rpcUrl, chainId, ...result };
|
return { rpcUrl, chainId, ...result };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -813,7 +818,7 @@ async function main() {
|
|||||||
for (let i = 0; i < networks.length; i++) {
|
for (let i = 0; i < networks.length; i++) {
|
||||||
const rpcUrl = networks[i];
|
const rpcUrl = networks[i];
|
||||||
const deployResult = deployResults[i];
|
const deployResult = deployResults[i];
|
||||||
const verificationResult = verificationResults[i];
|
const verificationResult = deployResult.verification || 'unknown';
|
||||||
const moduleResult = deployResult.modules?.[moduleType];
|
const moduleResult = deployResult.modules?.[moduleType];
|
||||||
const verification = verificationResult?.modules?.[moduleType] || 'unknown';
|
const verification = verificationResult?.modules?.[moduleType] || 'unknown';
|
||||||
|
|
||||||
@@ -916,15 +921,15 @@ async function main() {
|
|||||||
logger.info(`[MODULES_DBG] successCount: ${successCount}, totalCount: ${totalCount}`);
|
logger.info(`[MODULES_DBG] successCount: ${successCount}, totalCount: ${totalCount}`);
|
||||||
|
|
||||||
if (successCount === totalCount) {
|
if (successCount === totalCount) {
|
||||||
logger.info(`[MODULES_DBG] Вызываем finishDeploymentSession с success=true`);
|
logger.info(`[MODULES_DBG] Деплой завершен успешно! Задеплоено ${successCount} из ${totalCount} модулей`);
|
||||||
deploymentWebSocketService.finishDeploymentSession(dleAddress, true, `Деплой завершен успешно! Задеплоено ${successCount} из ${totalCount} модулей`);
|
|
||||||
} else {
|
} else {
|
||||||
logger.info(`[MODULES_DBG] Вызываем finishDeploymentSession с success=false`);
|
logger.info(`[MODULES_DBG] Деплой завершен с ошибками. Задеплоено ${successCount} из ${totalCount} модулей`);
|
||||||
deploymentWebSocketService.finishDeploymentSession(dleAddress, false, `Деплой завершен с ошибками. Задеплоено ${successCount} из ${totalCount} модулей`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Уведомляем об обновлении модулей
|
|
||||||
deploymentWebSocketService.notifyModulesUpdated(dleAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((e) => { logger.error(e); process.exit(1); });
|
main().catch((e) => {
|
||||||
|
logger.error('❌ Критическая ошибка в main():', e.message);
|
||||||
|
logger.error('❌ Stack trace:', e.stack);
|
||||||
|
logger.error('❌ Error details:', e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ async function deployInNetwork(rpcUrl, pk, initCodeHash, targetDLENonce, dleInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rc = await tx.wait();
|
const rc = await tx.wait(2); // Ждем 2 подтверждения с таймаутом
|
||||||
|
|
||||||
// Отмечаем транзакцию как подтвержденную в NonceManager
|
// Отмечаем транзакцию как подтвержденную в NonceManager
|
||||||
nonceManager.markTransactionConfirmed(wallet.address, chainId, tx.hash);
|
nonceManager.markTransactionConfirmed(wallet.address, chainId, tx.hash);
|
||||||
@@ -522,11 +522,22 @@ async function deployInNetwork(rpcUrl, pk, initCodeHash, targetDLENonce, dleInit
|
|||||||
const DLE = await hre.ethers.getContractFactory('contracts/DLE.sol:DLE');
|
const DLE = await hre.ethers.getContractFactory('contracts/DLE.sol:DLE');
|
||||||
const dleContract = DLE.attach(deployedAddress);
|
const dleContract = DLE.attach(deployedAddress);
|
||||||
|
|
||||||
const logoTx = await dleContract.connect(wallet).initializeLogoURI(params.logoURI, feeOverrides);
|
// Проверяем текущий логотип перед инициализацией
|
||||||
await logoTx.wait();
|
const currentLogo = await dleContract.logoURI();
|
||||||
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI initialized successfully`);
|
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} current logoURI: ${currentLogo}`);
|
||||||
|
|
||||||
|
if (currentLogo === '' || currentLogo === '0x') {
|
||||||
|
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI is empty, initializing...`);
|
||||||
|
const logoTx = await dleContract.connect(wallet).initializeLogoURI(params.logoURI, feeOverrides);
|
||||||
|
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI transaction sent: ${logoTx.hash}`);
|
||||||
|
await logoTx.wait(2); // Ждем 2 подтверждения с таймаутом
|
||||||
|
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI initialized successfully`);
|
||||||
|
} else {
|
||||||
|
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI already set: ${currentLogo}, skipping initialization`);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.info(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI initialization failed: ${error.message}`);
|
logger.error(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI initialization failed: ${error.message}`);
|
||||||
|
logger.error(`[MULTI_DBG] chainId=${Number(net.chainId)} error stack: ${error.stack}`);
|
||||||
// Не прерываем деплой из-за ошибки логотипа
|
// Не прерываем деплой из-за ошибки логотипа
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -15,12 +15,20 @@ class DeploymentWebSocketService {
|
|||||||
/**
|
/**
|
||||||
* Инициализация WebSocket сервера
|
* Инициализация WebSocket сервера
|
||||||
*/
|
*/
|
||||||
initialize(server) {
|
initialize(server, wss) {
|
||||||
// Теперь мы не создаем отдельный WebSocket сервер,
|
// Сохраняем ссылку на WebSocket сервер для отправки сообщений
|
||||||
// а работаем с основным WebSocket сервером через wsHub
|
this.wss = wss;
|
||||||
console.log('[DeploymentWS] WebSocket сервис для деплоя инициализирован');
|
console.log('[DeploymentWS] WebSocket сервис для деплоя инициализирован');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Установка WebSocket сервера (дополнительная инициализация)
|
||||||
|
*/
|
||||||
|
setWebSocketServer(wss) {
|
||||||
|
this.wss = wss;
|
||||||
|
console.log('[DeploymentWS] WebSocket сервер установлен, wss:', !!wss, 'clients:', wss ? wss.clients.size : 'N/A');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработка входящих сообщений
|
* Обработка входящих сообщений
|
||||||
*/
|
*/
|
||||||
@@ -220,12 +228,22 @@ class DeploymentWebSocketService {
|
|||||||
* Отправка сообщения всем клиентам конкретного DLE
|
* Отправка сообщения всем клиентам конкретного DLE
|
||||||
*/
|
*/
|
||||||
broadcastToDLE(dleAddress, message) {
|
broadcastToDLE(dleAddress, message) {
|
||||||
const clients = this.clients.get(dleAddress);
|
console.log('[DeploymentWS] broadcastToDLE вызвана, this.wss:', !!this.wss);
|
||||||
if (clients) {
|
if (!this.wss) {
|
||||||
clients.forEach(ws => {
|
console.warn('[DeploymentWS] WebSocket сервер не инициализирован');
|
||||||
this.sendToClient(ws, message);
|
return;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Отправляем сообщение всем подключенным клиентам
|
||||||
|
this.wss.clients.forEach(ws => {
|
||||||
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
|
try {
|
||||||
|
ws.send(JSON.stringify(message));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[DeploymentWS] Ошибка отправки сообщения:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,11 +31,19 @@ function initWSS(server) {
|
|||||||
wss = new WebSocket.Server({ server, path: '/ws' });
|
wss = new WebSocket.Server({ server, path: '/ws' });
|
||||||
console.log('🔌 [WebSocket] Сервер инициализирован на пути /ws');
|
console.log('🔌 [WebSocket] Сервер инициализирован на пути /ws');
|
||||||
|
|
||||||
|
// Инициализируем deploymentWebSocketService с WebSocket сервером после создания wss
|
||||||
|
deploymentWebSocketService.initialize(server, wss);
|
||||||
|
|
||||||
// Подключаем deployment tracker к WebSocket
|
// Подключаем deployment tracker к WebSocket
|
||||||
deploymentTracker.on('deployment_updated', (data) => {
|
deploymentTracker.on('deployment_updated', (data) => {
|
||||||
broadcastDeploymentUpdate(data);
|
broadcastDeploymentUpdate(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Дополнительная инициализация deploymentWebSocketService после создания wss
|
||||||
|
console.log('[wsHub] Инициализируем deploymentWebSocketService с wss:', !!wss);
|
||||||
|
deploymentWebSocketService.setWebSocketServer(wss);
|
||||||
|
console.log('[wsHub] deploymentWebSocketService инициализирован');
|
||||||
|
|
||||||
wss.on('connection', (ws, req) => {
|
wss.on('connection', (ws, req) => {
|
||||||
console.log('🔌 [WebSocket] Новое подключение');
|
console.log('🔌 [WebSocket] Новое подключение');
|
||||||
console.log('🔌 [WebSocket] IP клиента:', req.socket.remoteAddress);
|
console.log('🔌 [WebSocket] IP клиента:', req.socket.remoteAddress);
|
||||||
@@ -500,34 +508,7 @@ function broadcastDeploymentUpdate(data) {
|
|||||||
console.log(`📡 [WebSocket] Отправлено deployment update: deployment_update`);
|
console.log(`📡 [WebSocket] Отправлено deployment update: deployment_update`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для уведомления об обновлениях модулей
|
// broadcastModulesUpdate удалена - используем deploymentWebSocketService.broadcastToDLE
|
||||||
function broadcastModulesUpdate(dleAddress, updateType, moduleData) {
|
|
||||||
if (!wss) return;
|
|
||||||
|
|
||||||
console.log(`📡 [WebSocket] broadcastModulesUpdate вызвана для DLE: ${dleAddress}, тип: ${updateType}`);
|
|
||||||
|
|
||||||
const message = JSON.stringify({
|
|
||||||
type: updateType,
|
|
||||||
dleAddress: dleAddress,
|
|
||||||
moduleData: moduleData,
|
|
||||||
timestamp: Date.now()
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`📡 [WebSocket] Отправляем сообщение модулей:`, message);
|
|
||||||
|
|
||||||
// Отправляем всем подключенным клиентам
|
|
||||||
wss.clients.forEach(client => {
|
|
||||||
if (client.readyState === WebSocket.OPEN) {
|
|
||||||
try {
|
|
||||||
client.send(message);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[WebSocket] Ошибка при отправке modules update:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`📡 [WebSocket] Отправлено modules update: ${updateType} для DLE: ${dleAddress}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
initWSS,
|
initWSS,
|
||||||
@@ -548,7 +529,6 @@ module.exports = {
|
|||||||
broadcastTokenBalancesUpdate,
|
broadcastTokenBalancesUpdate,
|
||||||
broadcastTokenBalanceChanged,
|
broadcastTokenBalanceChanged,
|
||||||
broadcastDeploymentUpdate,
|
broadcastDeploymentUpdate,
|
||||||
broadcastModulesUpdate,
|
|
||||||
getConnectedUsers,
|
getConnectedUsers,
|
||||||
getStats
|
getStats
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1207,6 +1207,12 @@ function connectModulesWebSocket() {
|
|||||||
function handleModulesWebSocketMessage(data) {
|
function handleModulesWebSocketMessage(data) {
|
||||||
console.log('[ModulesView] WebSocket модулей сообщение:', data);
|
console.log('[ModulesView] WebSocket модулей сообщение:', data);
|
||||||
|
|
||||||
|
// Обрабатываем deployment_log в модульном WebSocket
|
||||||
|
if (data.type === 'deployment_log') {
|
||||||
|
addLog(data.log.type, data.log.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Обрабатываем только сообщения, связанные с модулями, не с деплоем
|
// Обрабатываем только сообщения, связанные с модулями, не с деплоем
|
||||||
if (data.type && data.type.startsWith('deployment_')) {
|
if (data.type && data.type.startsWith('deployment_')) {
|
||||||
console.log('[ModulesView] Пропускаем сообщение о деплое в модульном WebSocket');
|
console.log('[ModulesView] Пропускаем сообщение о деплое в модульном WebSocket');
|
||||||
|
|||||||
Reference in New Issue
Block a user