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

This commit is contained in:
2025-12-01 22:05:31 +03:00
parent 6dacba2786
commit 90da3a0d12
10 changed files with 475 additions and 347 deletions

26
.gitignore vendored
View File

@@ -98,9 +98,6 @@ typings/
*.swp
*.swo
# Backup files
*.bak
# OS
.DS_Store
Thumbs.db
@@ -125,12 +122,6 @@ frontend/uploads/
# Database migrations (may contain sensitive data)
backend/db/migrations/
# Keys and certificates
*.key
*.pem
*.crt
*.p12
# SSH Keys - КРИТИЧЕСКИ ВАЖНО!
id_rsa
id_ed25519
@@ -138,14 +129,16 @@ id_ed25519
ssh_host_*
ssh_config
# SSL Keys and certificates - КРИТИЧЕСКИ ВАЖНО!
ssl/keys/
ssl/certs/
# Keys and certificates - КРИТИЧЕСКИ ВАЖНО!
*.key
*.pem
*.crt
*.p12
# SSL Keys and certificates - КРИТИЧЕСКИ ВАЖНО!
ssl/keys/
ssl/certs/
# Database encryption keys - КРИТИЧЕСКИ ВАЖНО!
**/full_db_encryption.key
**/ssl/full_db_encryption.key
@@ -207,17 +200,10 @@ backend/.env.production
# Server management scripts - may contain sensitive information
scripts/clean-server.sh
scripts/export-template-for-release.sh
scripts/replace-release-assets.sh
# Docker data and release archives - не коммитить в Git!
docker-data/
dle-template.tar.gz
dle-template.tar.gz.part-*
dle-template.tar.gz.join.sh
# Guide files
pages-guide.md
# Problem documentation (internal)
SIWE_PROBLEM.md
REBUILD_COMMANDS.md
SIWE_ISSUE_DESCRIPTION.md

File diff suppressed because it is too large Load Diff

View File

@@ -26,41 +26,45 @@ function getNetworks() {
// Получаем RPC URLs из переменных окружения
const rpcUrlsEnv = process.env.RPC_URLS;
const rpcUrls = rpcUrlsEnv ? JSON.parse(rpcUrlsEnv) : {};
// console.log удален - может мешать flatten
// Базовые сети - УБРАНО, используем только базу данных
const baseNetworks = {}; // Пустой объект - никаких хардкод цепочек
// Если есть supported_chain_ids, фильтруем только нужные сети
if (supportedChainIds.length > 0) {
const networks = {};
const supportedChainIdsNumbers = supportedChainIds.map(id => Number(id));
for (const [networkName, networkConfig] of Object.entries(baseNetworks)) {
if (supportedChainIdsNumbers.includes(networkConfig.chainId)) {
// Используем RPC URL из переменных окружения если есть
const customRpcUrl = rpcUrls[networkConfig.chainId] || rpcUrls[networkConfig.chainId.toString()];
if (customRpcUrl) {
networkConfig.url = customRpcUrl;
// console.log удален - может мешать flatten
}
networks[networkName] = networkConfig;
}
}
// console.log удален - может мешать flatten
return networks;
} else {
// Если нет supported_chain_ids, используем все базовые сети
// console.log удален - может мешать flatten
return baseNetworks;
// Если нет supported_chain_ids, ничего не настраиваем (используются только локальные сети Hardhat)
if (!supportedChainIds || supportedChainIds.length === 0) {
return {};
}
const networks = {};
const supportedChainIdsNumbers = supportedChainIds.map((id) => Number(id));
// RPC_URLS может быть либо объектом { [chainId]: url }, либо массивом URL-ов.
const isRpcArray = Array.isArray(rpcUrls);
supportedChainIdsNumbers.forEach((chainId, index) => {
let url;
if (isRpcArray) {
url = rpcUrls[index];
} else {
url = rpcUrls[chainId] || rpcUrls[chainId.toString()];
}
if (!url) {
// Если для chainId нет URL — пропускаем сеть
return;
}
const networkName = `chain_${chainId}`;
networks[networkName] = {
chainId,
url
// accounts не указываем: для verify достаточно RPC + ETHERSCAN_API_KEY
};
});
return networks;
}
// Функция для получения базовых сетей (fallback) - УБРАНО, используем только базу данных
// Функция для получения базовых сетей (fallback) — оставлена для совместимости
function getBaseNetworks() {
return {}; // Пустой объект - никаких хардкод цепочек
return {};
}

View File

@@ -0,0 +1,64 @@
{
"deploymentId": "modules-deploy-1764614264868",
"dleAddress": "0x692a9B9520e63F0CC3f4d2E0458cd4d82cCFd437",
"dleName": "DLE-TEST",
"dleSymbol": "DLET",
"dleLocation": "101000, Москва, Москва, Тверская, 1, 10",
"dleJurisdiction": 643,
"dleCoordinates": "55.7613657,37.63428",
"dleOktmo": "45000000",
"dleOkvedCodes": [
"62.01.1"
],
"dleKpp": "773001001",
"dleLogoURI": "/uploads/logos/default-token.svg",
"dleSupportedChainIds": [
11155111,
421614,
84532
],
"totalNetworks": 3,
"successfulNetworks": 3,
"modulesDeployed": [
"treasury"
],
"networks": [
{
"chainId": 11155111,
"rpcUrl": "https://1rpc.io/sepolia",
"modules": [
{
"type": "treasury",
"address": "0x9dF6640F52ffCAfD86DE143241565edE069720Bc",
"success": true,
"verification": "verified"
}
]
},
{
"chainId": 421614,
"rpcUrl": "https://sepolia-rollup.arbitrum.io/rpc",
"modules": [
{
"type": "treasury",
"address": "0x9dF6640F52ffCAfD86DE143241565edE069720Bc",
"success": true,
"verification": "verified"
}
]
},
{
"chainId": 84532,
"rpcUrl": "https://sepolia.base.org",
"modules": [
{
"type": "treasury",
"address": "0x9dF6640F52ffCAfD86DE143241565edE069720Bc",
"success": true,
"verification": "verified"
}
]
}
],
"timestamp": "2025-12-01T18:37:44.868Z"
}

View File

@@ -74,32 +74,16 @@ const MODULE_CONFIGS = {
// }
};
// Функция для определения имени сети Hardhat по chainId
// Функция для определения имени сети Hardhat по chainId (динамически, без хардкода)
// В hardhat.config.js сети объявляются как chain_<chainId>
function getNetworkNameForHardhat(chainId) {
const networkMapping = {
11155111: 'sepolia',
17000: 'holesky',
421614: 'arbitrumSepolia',
84532: 'baseSepolia',
1: 'mainnet',
42161: 'arbitrumOne',
8453: 'base',
137: 'polygon',
56: 'bsc'
};
const hardhatNetworkName = networkMapping[chainId];
if (!hardhatNetworkName) {
logger.warn(`⚠️ Сеть ${chainId} не поддерживается в Hardhat`);
return null;
}
logger.info(`✅ Сеть ${chainId} поддерживается: ${hardhatNetworkName}`);
const hardhatNetworkName = `chain_${Number(chainId)}`;
logger.info(`✅ Сеть ${chainId} будет использовать Hardhat network: ${hardhatNetworkName}`);
return hardhatNetworkName;
}
// Функция для автоматической верификации модуля
async function verifyModuleAfterDeploy(chainId, contractAddress, moduleType, constructorArgs, apiKey) {
async function verifyModuleAfterDeploy(chainId, contractAddress, moduleType, constructorArgs, apiKey, params = {}) {
try {
if (!apiKey) {
logger.warn(`⚠️ API ключ Etherscan не предоставлен, пропускаем верификацию модуля ${moduleType}`);
@@ -143,10 +127,17 @@ async function verifyModuleAfterDeploy(chainId, contractAddress, moduleType, con
const command = `npx hardhat verify --network ${networkName} --constructor-args ${tempArgsFile} ${contractAddress}`;
logger.info(`🔧 Выполняем команду: ${command}`);
// Устанавливаем переменные окружения для Hardhat
// Устанавливаем переменные окружения для Hardhat (в том числе сети и RPC из deploy params)
const envVars = {
...process.env,
ETHERSCAN_API_KEY: apiKey
ETHERSCAN_API_KEY: apiKey || params.etherscanApiKey || '',
SUPPORTED_CHAIN_IDS: JSON.stringify(
params.supportedChainIds || params.supported_chain_ids || [chainId]
),
RPC_URLS: JSON.stringify(
// params.rpcUrls / params.rpc_urls могут быть либо массивом, либо объектом { [chainId]: url }
params.rpcUrls || params.rpc_urls || {}
)
};
const { stdout, stderr } = await execAsync(command, {
@@ -428,9 +419,9 @@ async function deployAllModulesInNetwork(chainId, pk, salt, dleAddress, modulesT
});
const net = network;
const chainId = Number(net.chainId);
const numericChainId = Number(net.chainId);
logger.info(`[MODULES_DBG] chainId=${chainId} deploying modules: ${modulesToDeploy.join(', ')}`);
logger.info(`[MODULES_DBG] chainId=${numericChainId} deploying modules: ${modulesToDeploy.join(', ')}`);
const results = {};
@@ -443,14 +434,14 @@ async function deployAllModulesInNetwork(chainId, pk, salt, dleAddress, modulesT
logger.info(`[MODULES_DBG] Деплой модуля ${moduleType} в сети ${net.name || net.chainId}`);
if (!MODULE_CONFIGS[moduleType]) {
logger.error(`[MODULES_DBG] chainId=${chainId} Unknown module type: ${moduleType}`);
logger.error(`[MODULES_DBG] chainId=${numericChainId} Unknown module type: ${moduleType}`);
results[moduleType] = { success: false, error: `Unknown module type: ${moduleType}` };
logger.error(`[MODULES_DBG] Неизвестный тип модуля: ${moduleType}`);
continue;
}
if (!moduleInit) {
logger.error(`[MODULES_DBG] chainId=${chainId} No init code for module: ${moduleType}`);
logger.error(`[MODULES_DBG] chainId=${numericChainId} No init code for module: ${moduleType}`);
results[moduleType] = { success: false, error: `No init code for module: ${moduleType}` };
logger.error(`[MODULES_DBG] Отсутствует код инициализации для модуля: ${moduleType}`);
continue;
@@ -469,7 +460,7 @@ async function deployAllModulesInNetwork(chainId, pk, salt, dleAddress, modulesT
// Получаем аргументы конструктора для модуля
const moduleConfig = MODULE_CONFIGS[moduleType];
const constructorArgs = moduleConfig.constructorArgs(dleAddress, chainId, wallet.address);
const constructorArgs = moduleConfig.constructorArgs(dleAddress, numericChainId, wallet.address);
// Ждем 30 секунд перед верификацией, чтобы транзакция получила подтверждения
logger.info(`[MODULES_DBG] Ждем 30 секунд перед верификацией модуля ${moduleType}...`);
@@ -477,7 +468,7 @@ async function deployAllModulesInNetwork(chainId, pk, salt, dleAddress, modulesT
// Проверяем, что контракт действительно задеплоен
try {
const { provider } = await createRPCConnection(rpcUrl, pk, { maxRetries: 3, timeout: 30000 });
const { provider } = await createRPCConnection(numericChainId, pk, { maxRetries: 3, timeout: 30000 });
const code = await provider.getCode(result.address);
if (!code || code === '0x') {
logger.warn(`[MODULES_DBG] Контракт ${moduleType} не найден по адресу ${result.address}, пропускаем верификацию`);
@@ -489,11 +480,12 @@ async function deployAllModulesInNetwork(chainId, pk, salt, dleAddress, modulesT
}
const verificationResult = await verifyModuleAfterDeploy(
chainId,
numericChainId,
result.address,
moduleType,
constructorArgs,
params.etherscanApiKey
params.etherscanApiKey,
params
);
if (verificationResult.success) {
@@ -542,16 +534,9 @@ async function deployAllModulesInNetwork(chainId, pk, salt, dleAddress, modulesT
async function deployAllModulesInAllNetworks(networks, pk, salt, dleAddress, modulesToDeploy, moduleInits, targetNonces) {
const results = [];
for (let i = 0; i < connections.length; i++) {
const connection = connections[i];
const rpcUrl = connection.rpcUrl;
logger.info(`[MODULES_DBG] deploying modules to network ${i + 1}/${connections.length}: ${rpcUrl}`);
const result = await deployAllModulesInNetwork(rpcUrl, pk, salt, dleAddress, modulesToDeploy, moduleInits, targetNonces);
results.push(result);
}
return results;
// Функция больше не используется (логика деплоя реализована через connections в main)
// Оставлена для совместимости.
return [];
}
async function main() {
@@ -849,38 +834,22 @@ async function main() {
};
// Собираем информацию о всех сетях для этого модуля
for (let i = 0; i < networks.length; i++) {
const rpcUrl = networks[i];
for (let i = 0; i < deployResults.length; i++) {
const deployResult = deployResults[i];
const verificationResult = deployResult.verification || 'unknown';
const rpcUrl = deployResult.rpcUrl;
const moduleResult = deployResult.modules?.[moduleType];
const verification = verificationResult?.modules?.[moduleType] || 'unknown';
try {
const { provider, network } = await createRPCConnection(rpcUrl, pk, {
maxRetries: 3,
timeout: 30000
});
moduleInfo.networks.push({
chainId: Number(network.chainId),
rpcUrl: rpcUrl,
address: moduleResult?.success ? moduleResult.address : null,
verification: verification,
success: moduleResult?.success || false,
error: moduleResult?.error || null
});
} catch (error) {
logger.error(`[MODULES_DBG] Ошибка получения chainId для модуля ${moduleType} в сети ${i + 1}:`, error.message);
moduleInfo.networks.push({
chainId: null,
rpcUrl: rpcUrl,
address: null,
verification: 'error',
success: false,
error: error.message
});
}
// Верификационный статус уже хранится в deployResult.modules[moduleType].verification
const verification = moduleResult?.verification || 'unknown';
moduleInfo.networks.push({
chainId: deployResult.chainId ?? null,
rpcUrl: rpcUrl,
address: moduleResult?.success ? moduleResult.address : null,
verification: verification,
success: moduleResult?.success || false,
error: moduleResult?.error || null
});
}
// Сохраняем файл модуля

View File

@@ -54,26 +54,6 @@ console.log('[MULTI_DBG] main:', typeof main);
// Функция для получения имени сети для Hardhat из deploy_params
function getNetworkNameForHardhat(chainId, params) {
// Создаем маппинг chainId -> Hardhat network name
const networkMapping = {
11155111: 'sepolia',
17000: 'holesky',
421614: 'arbitrumSepolia',
84532: 'baseSepolia',
1: 'mainnet',
42161: 'arbitrumOne',
8453: 'base',
137: 'polygon',
56: 'bsc'
};
// Проверяем, поддерживается ли сеть в Hardhat
const hardhatNetworkName = networkMapping[chainId];
if (!hardhatNetworkName) {
logger.warn(`⚠️ Сеть ${chainId} не поддерживается в Hardhat`);
return null;
}
// Проверяем, есть ли эта сеть в supported_chain_ids из deploy_params
const supportedChainIds = params.supported_chain_ids || params.supportedChainIds || [];
if (supportedChainIds.length > 0) {
@@ -88,7 +68,10 @@ function getNetworkNameForHardhat(chainId, params) {
logger.info(` Список поддерживаемых сетей пуст, разрешаем верификацию для ${chainId}`);
}
logger.info(`✅ Сеть ${chainId} поддерживается: ${hardhatNetworkName}`);
// Динамически формируем имя сети для Hardhat без хардкода:
// в конфиге Hardhat сеть будет объявлена как chain_<chainId>
const hardhatNetworkName = `chain_${chainId}`;
logger.info(`✅ Сеть ${chainId} будет использовать Hardhat network: ${hardhatNetworkName}`);
logger.info(`🔍 Детали сети: chainId=${chainId}, hardhatName=${hardhatNetworkName}, supportedChains=[${supportedChainIds.join(', ')}]`);
return hardhatNetworkName;
}
@@ -824,11 +807,16 @@ async function main() {
}));
// ВЫВОДИМ РЕЗУЛЬТАТ С ИНТЕГРИРОВАННОЙ ВЕРИФИКАЦИЕЙ!
console.log('[MULTI_DBG] 🎯 ДОШЛИ ДО ВЫВОДА РЕЗУЛЬТАТА!');
console.log('[MULTI_DBG] 📊 finalResults:', JSON.stringify(finalResults, null, 2));
console.log('[MULTI_DBG] 🎯 ВЫВОДИМ MULTICHAIN_DEPLOY_RESULT!');
console.log('MULTICHAIN_DEPLOY_RESULT', JSON.stringify(finalResults));
console.log('[MULTI_DBG] ✅ MULTICHAIN_DEPLOY_RESULT ВЫВЕДЕН!');
// Важно: используем process.stdout.write, чтобы обойти маскирование адресов (logger/console)
logger.info('[MULTI_DBG] 🎯 ДОШЛИ ДО ВЫВОДА РЕЗУЛЬТАТА!');
logger.info('[MULTI_DBG] 📊 finalResults:', finalResults);
logger.info('[MULTI_DBG] 🎯 ВЫВОДИМ MULTICHAIN_DEPLOY_RESULT!');
const rawResult = JSON.stringify(finalResults);
// Эту строку парсят unifiedDeploymentService и dleV2Service по шаблону /MULTICHAIN_DEPLOY_RESULT\\s+(.+)/
process.stdout.write(`MULTICHAIN_DEPLOY_RESULT ${rawResult}\n`);
logger.info('[MULTI_DBG] ✅ MULTICHAIN_DEPLOY_RESULT ВЫВЕДЕН!');
logger.info('[MULTI_DBG] DLE deployment completed successfully with integrated verification!');
}
@@ -845,7 +833,9 @@ main().catch((e) => {
stack: e.stack
};
console.log('MULTICHAIN_DEPLOY_RESULT', JSON.stringify([errorResult]));
// Даже в случае ошибки выводим сырой результат без маскирования
const rawError = JSON.stringify([errorResult]);
process.stdout.write(`MULTICHAIN_DEPLOY_RESULT ${rawError}\n`);
process.exit(1);
});

View File

@@ -446,7 +446,7 @@ const loadDleData = async () => {
console.log('Начинаем загрузку данных DLE для адреса:', dleAddress.value);
isLoadingDle.value = true;
try {
const response = await api.post('/dle-core/read-dle-info', {
const response = await api.post('/blockchain/read-dle-info', {
dleAddress: dleAddress.value
});

View File

@@ -311,7 +311,7 @@ async function loadDleData() {
console.log('[AnalyticsView] Загрузка данных DLE:', dleAddress.value);
// Читаем данные из блокчейна
const response = await api.post('/dle-core/read-dle-info', {
const response = await api.post('/blockchain/read-dle-info', {
dleAddress: dleAddress.value
});

View File

@@ -309,7 +309,7 @@ async function loadDleData() {
isLoadingDle.value = true;
try {
// Загружаем данные DLE из блокчейна
const response = await api.post('/dle-core/read-dle-info', {
const response = await api.post('/blockchain/read-dle-info', {
dleAddress: dleAddress.value
});

View File

@@ -325,7 +325,7 @@ async function loadDleData() {
console.log('[HistoryView] Загрузка данных DLE:', dleAddress.value);
// Читаем данные из блокчейна
const response = await api.post('/dle-core/read-dle-info', {
const response = await api.post('/blockchain/read-dle-info', {
dleAddress: dleAddress.value
});