diff --git a/backend/routes/blockchain.js b/backend/routes/blockchain.js index d087cf4..f1cb6ca 100644 --- a/backend/routes/blockchain.js +++ b/backend/routes/blockchain.js @@ -64,7 +64,8 @@ router.post('/read-dle-info', async (req, res) => { "function totalSupply() external view returns (uint256)", "function balanceOf(address account) external view returns (uint256)", "function quorumPercentage() external view returns (uint256)", - "function getCurrentChainId() external view returns (uint256)" + "function getCurrentChainId() external view returns (uint256)", + "function logoURI() external view returns (string memory)" ]; const dle = new ethers.Contract(dleAddress, dleAbi, provider); @@ -74,22 +75,103 @@ router.post('/read-dle-info', async (req, res) => { const totalSupply = await dle.totalSupply(); const quorumPercentage = await dle.quorumPercentage(); const currentChainId = await dle.getCurrentChainId(); - - // Проверяем баланс создателя (адрес, который деплоил контракт) - const deployer = "0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B"; - const deployerBalance = await dle.balanceOf(deployer); - - // Определяем количество участников (держателей токенов) - let participantCount = 0; - if (deployerBalance > 0) { - participantCount++; + + // Читаем логотип + let logoURI = ''; + try { + logoURI = await dle.logoURI(); + } catch (error) { + console.log(`[Blockchain] Ошибка при чтении logoURI:`, error.message); } - // Проверяем, есть ли другие держатели токенов - // Для простоты считаем, что если создатель имеет меньше 100% токенов, то есть другие участники - const deployerPercentage = (Number(deployerBalance) / Number(totalSupply)) * 100; - if (deployerPercentage < 100) { - participantCount = Math.max(participantCount, 2); // Минимум 2 участника + // Получаем информацию о партнерах из блокчейна + const partnerBalances = []; + let participantCount = 0; + + // Получаем события InitialTokensDistributed для определения партнеров + try { + // Получаем последние блоки для поиска событий + const currentBlock = await provider.getBlockNumber(); + const fromBlock = Math.max(0, currentBlock - 10000); // Ищем в последних 10000 блоках + + // ABI для события InitialTokensDistributed + const eventAbi = [ + "event InitialTokensDistributed(address[] partners, uint256[] amounts)" + ]; + + const dleWithEvents = new ethers.Contract(dleAddress, [...dleAbi, ...eventAbi], provider); + + // Ищем события InitialTokensDistributed + const events = await dleWithEvents.queryFilter( + dleWithEvents.filters.InitialTokensDistributed(), + fromBlock, + currentBlock + ); + + if (events.length > 0) { + // Берем последнее событие + const lastEvent = events[events.length - 1]; + const partners = lastEvent.args.partners; + const amounts = lastEvent.args.amounts; + + for (let i = 0; i < partners.length; i++) { + const partnerAddress = partners[i]; + const amount = amounts[i]; + + // Проверяем текущий баланс + const currentBalance = await dle.balanceOf(partnerAddress); + if (Number(currentBalance) > 0) { + participantCount++; + partnerBalances.push({ + address: partnerAddress, + balance: ethers.formatUnits(currentBalance, 18), + percentage: (Number(currentBalance) / Number(totalSupply)) * 100, + initialAmount: ethers.formatUnits(amount, 18) + }); + } + } + } + } catch (error) { + console.log(`[Blockchain] Ошибка при получении событий партнеров:`, error.message); + + // Fallback: ищем держателей токенов через события Transfer + try { + const currentBlock = await provider.getBlockNumber(); + const fromBlock = Math.max(0, currentBlock - 10000); + + const transferEventAbi = [ + "event Transfer(address indexed from, address indexed to, uint256 value)" + ]; + + const dleWithTransferEvents = new ethers.Contract(dleAddress, [...dleAbi, ...transferEventAbi], provider); + + // Ищем события Transfer с from = address(0) (mint события) + const mintEvents = await dleWithTransferEvents.queryFilter( + dleWithTransferEvents.filters.Transfer(ethers.ZeroAddress), + fromBlock, + currentBlock + ); + + const uniqueRecipients = new Set(); + for (const event of mintEvents) { + uniqueRecipients.add(event.args.to); + } + + // Проверяем текущие балансы всех получателей + for (const recipient of uniqueRecipients) { + const balance = await dle.balanceOf(recipient); + if (Number(balance) > 0) { + participantCount++; + partnerBalances.push({ + address: recipient, + balance: ethers.formatUnits(balance, 18), + percentage: (Number(balance) / Number(totalSupply)) * 100 + }); + } + } + } catch (fallbackError) { + console.log(`[Blockchain] Ошибка при fallback поиске партнеров:`, fallbackError.message); + } } const blockchainData = { @@ -106,7 +188,8 @@ router.post('/read-dle-info', async (req, res) => { creationTimestamp: Number(dleInfo.creationTimestamp), isActive: dleInfo.isActive, totalSupply: ethers.formatUnits(totalSupply, 18), - deployerBalance: ethers.formatUnits(deployerBalance, 18), + partnerBalances: partnerBalances, // Информация о партнерах и их балансах + logoURI: logoURI, // URL логотипа токена quorumPercentage: Number(quorumPercentage), currentChainId: Number(currentChainId), rpcUsed: rpcUrl, diff --git a/backend/routes/dleCore.js b/backend/routes/dleCore.js index 07544f6..2e8daf6 100644 --- a/backend/routes/dleCore.js +++ b/backend/routes/dleCore.js @@ -46,7 +46,8 @@ router.post('/read-dle-info', async (req, res) => { "function totalSupply() external view returns (uint256)", "function balanceOf(address account) external view returns (uint256)", "function quorumPercentage() external view returns (uint256)", - "function getCurrentChainId() external view returns (uint256)" + "function getCurrentChainId() external view returns (uint256)", + "function logoURI() external view returns (string memory)" ]; const dle = new ethers.Contract(dleAddress, dleAbi, provider); @@ -56,22 +57,103 @@ router.post('/read-dle-info', async (req, res) => { const totalSupply = await dle.totalSupply(); const quorumPercentage = await dle.quorumPercentage(); const currentChainId = await dle.getCurrentChainId(); - - // Проверяем баланс создателя (адрес, который деплоил контракт) - const deployer = "0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B"; - const deployerBalance = await dle.balanceOf(deployer); - - // Определяем количество участников (держателей токенов) - let participantCount = 0; - if (deployerBalance > 0) { - participantCount++; + + // Читаем логотип + let logoURI = ''; + try { + logoURI = await dle.logoURI(); + } catch (error) { + console.log(`[DLE Core] Ошибка при чтении logoURI:`, error.message); } - // Проверяем, есть ли другие держатели токенов - // Для простоты считаем, что если создатель имеет меньше 100% токенов, то есть другие участники - const deployerPercentage = (Number(deployerBalance) / Number(totalSupply)) * 100; - if (deployerPercentage < 100) { - participantCount = Math.max(participantCount, 2); // Минимум 2 участника + // Получаем информацию о партнерах из блокчейна + const partnerBalances = []; + let participantCount = 0; + + // Получаем события InitialTokensDistributed для определения партнеров + try { + // Получаем последние блоки для поиска событий + const currentBlock = await provider.getBlockNumber(); + const fromBlock = Math.max(0, currentBlock - 10000); // Ищем в последних 10000 блоках + + // ABI для события InitialTokensDistributed + const eventAbi = [ + "event InitialTokensDistributed(address[] partners, uint256[] amounts)" + ]; + + const dleWithEvents = new ethers.Contract(dleAddress, [...dleAbi, ...eventAbi], provider); + + // Ищем события InitialTokensDistributed + const events = await dleWithEvents.queryFilter( + dleWithEvents.filters.InitialTokensDistributed(), + fromBlock, + currentBlock + ); + + if (events.length > 0) { + // Берем последнее событие + const lastEvent = events[events.length - 1]; + const partners = lastEvent.args.partners; + const amounts = lastEvent.args.amounts; + + for (let i = 0; i < partners.length; i++) { + const partnerAddress = partners[i]; + const amount = amounts[i]; + + // Проверяем текущий баланс + const currentBalance = await dle.balanceOf(partnerAddress); + if (Number(currentBalance) > 0) { + participantCount++; + partnerBalances.push({ + address: partnerAddress, + balance: ethers.formatUnits(currentBalance, 18), + percentage: (Number(currentBalance) / Number(totalSupply)) * 100, + initialAmount: ethers.formatUnits(amount, 18) + }); + } + } + } + } catch (error) { + console.log(`[DLE Core] Ошибка при получении событий партнеров:`, error.message); + + // Fallback: ищем держателей токенов через события Transfer + try { + const currentBlock = await provider.getBlockNumber(); + const fromBlock = Math.max(0, currentBlock - 10000); + + const transferEventAbi = [ + "event Transfer(address indexed from, address indexed to, uint256 value)" + ]; + + const dleWithTransferEvents = new ethers.Contract(dleAddress, [...dleAbi, ...transferEventAbi], provider); + + // Ищем события Transfer с from = address(0) (mint события) + const mintEvents = await dleWithTransferEvents.queryFilter( + dleWithTransferEvents.filters.Transfer(ethers.ZeroAddress), + fromBlock, + currentBlock + ); + + const uniqueRecipients = new Set(); + for (const event of mintEvents) { + uniqueRecipients.add(event.args.to); + } + + // Проверяем текущие балансы всех получателей + for (const recipient of uniqueRecipients) { + const balance = await dle.balanceOf(recipient); + if (Number(balance) > 0) { + participantCount++; + partnerBalances.push({ + address: recipient, + balance: ethers.formatUnits(balance, 18), + percentage: (Number(balance) / Number(totalSupply)) * 100 + }); + } + } + } catch (fallbackError) { + console.log(`[DLE Core] Ошибка при fallback поиске партнеров:`, fallbackError.message); + } } const blockchainData = { @@ -87,7 +169,8 @@ router.post('/read-dle-info', async (req, res) => { creationTimestamp: Number(dleInfo.creationTimestamp), isActive: dleInfo.isActive, totalSupply: ethers.formatUnits(totalSupply, 18), - deployerBalance: ethers.formatUnits(deployerBalance, 18), + partnerBalances: partnerBalances, // Информация о партнерах и их балансах + logoURI: logoURI, // URL логотипа токена quorumPercentage: Number(quorumPercentage), currentChainId: Number(currentChainId), participantCount: participantCount diff --git a/backend/routes/dleModules.js b/backend/routes/dleModules.js index d7c62d0..01d84c5 100644 --- a/backend/routes/dleModules.js +++ b/backend/routes/dleModules.js @@ -66,6 +66,37 @@ router.post('/is-module-active', async (req, res) => { } }); +// Получить информацию о задеплоенных модулях для DLE +router.get('/deployed/:dleAddress', async (req, res) => { + try { + const { dleAddress } = req.params; + + if (!dleAddress) { + return res.status(400).json({ + success: false, + error: 'Адрес DLE обязателен' + }); + } + + console.log(`[DLE Modules] Получение информации о модулях для DLE: ${dleAddress}`); + + // Получаем информацию о модулях из файлов деплоя + const modulesInfo = await getDeployedModulesInfo(dleAddress); + + res.json({ + success: true, + data: modulesInfo + }); + + } catch (error) { + console.error('[DLE Modules] Ошибка при получении информации о модулях:', error); + res.status(500).json({ + success: false, + error: 'Ошибка при получении информации о модулях: ' + error.message + }); + } +}); + // Получить адрес модуля router.post('/get-module-address', async (req, res) => { try { @@ -300,4 +331,45 @@ router.post('/create-remove-module-proposal', async (req, res) => { } }); +// Функция для получения информации о задеплоенных модулях +async function getDeployedModulesInfo(dleAddress) { + const fs = require('fs'); + const path = require('path'); + + try { + // Ищем файл модулей для конкретного DLE + const deployDir = path.join(__dirname, '../temp'); + if (!fs.existsSync(deployDir)) { + return { modules: [], verification: {} }; + } + + // Ищем файл по адресу DLE + const modulesFileName = `modules-${dleAddress.toLowerCase()}.json`; + const modulesFilePath = path.join(deployDir, modulesFileName); + + if (!fs.existsSync(modulesFilePath)) { + console.log(`[DLE Modules] Файл модулей не найден: ${modulesFileName}`); + return { modules: [], verification: {} }; + } + + try { + const data = JSON.parse(fs.readFileSync(modulesFilePath, 'utf8')); + console.log(`[DLE Modules] Загружена информация о модулях для DLE: ${dleAddress}`); + + return { + modules: data.modules || [], + verification: data.verification || {}, + deployTimestamp: data.deployTimestamp + }; + } catch (error) { + console.error(`Ошибка при чтении файла ${modulesFileName}:`, error); + return { modules: [], verification: {} }; + } + + } catch (error) { + console.error('Ошибка при получении информации о модулях:', error); + return { modules: [], verification: {} }; + } +} + module.exports = router; diff --git a/backend/scripts/deploy/deploy-multichain.js b/backend/scripts/deploy/deploy-multichain.js index 44b1f7b..fa305d7 100644 --- a/backend/scripts/deploy/deploy-multichain.js +++ b/backend/scripts/deploy/deploy-multichain.js @@ -173,6 +173,230 @@ async function deployInNetwork(rpcUrl, pk, salt, initCodeHash, targetDLENonce, d return { address: deployedAddress, chainId: Number(net.chainId) }; } +// Деплой модулей в одной сети +async function deployModulesInNetwork(rpcUrl, pk, dleAddress) { + const { ethers } = hre; + const provider = new ethers.JsonRpcProvider(rpcUrl); + const wallet = new ethers.Wallet(pk, provider); + const net = await provider.getNetwork(); + + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} deploying modules...`); + + const modules = {}; + + try { + // Деплой TreasuryModule + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} deploying TreasuryModule...`); + const TreasuryModule = await hre.ethers.getContractFactory('TreasuryModule'); + const treasuryModule = await TreasuryModule.connect(wallet).deploy( + dleAddress, // _dleContract + Number(net.chainId), // _chainId + wallet.address // _emergencyAdmin + ); + await treasuryModule.waitForDeployment(); + const treasuryAddress = await treasuryModule.getAddress(); + modules.treasuryModule = treasuryAddress; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} TreasuryModule deployed at: ${treasuryAddress}`); + + // Деплой TimelockModule + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} deploying TimelockModule...`); + const TimelockModule = await hre.ethers.getContractFactory('TimelockModule'); + const timelockModule = await TimelockModule.connect(wallet).deploy( + dleAddress // _dleContract + ); + await timelockModule.waitForDeployment(); + const timelockAddress = await timelockModule.getAddress(); + modules.timelockModule = timelockAddress; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} TimelockModule deployed at: ${timelockAddress}`); + + // Деплой DLEReader + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} deploying DLEReader...`); + const DLEReader = await hre.ethers.getContractFactory('DLEReader'); + const dleReader = await DLEReader.connect(wallet).deploy( + dleAddress // _dleContract + ); + await dleReader.waitForDeployment(); + const readerAddress = await dleReader.getAddress(); + modules.dleReader = readerAddress; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} DLEReader deployed at: ${readerAddress}`); + + // Инициализация модулей в DLE + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} initializing modules in DLE...`); + const dleContract = await hre.ethers.getContractAt('DLE', dleAddress, wallet); + + // Инициализация базовых модулей + await dleContract.initializeBaseModules(treasuryAddress, timelockAddress, readerAddress); + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} base modules initialized`); + + // Инициализация logoURI + try { + // Используем логотип из параметров деплоя или fallback + const logoURL = params.logoURI || "https://via.placeholder.com/200x200/0066cc/ffffff?text=DLE"; + await dleContract.initializeLogoURI(logoURL); + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI initialized: ${logoURL}`); + } catch (e) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} logoURI initialization failed: ${e.message}`); + // Fallback на базовый логотип + try { + await dleContract.initializeLogoURI("https://via.placeholder.com/200x200/0066cc/ffffff?text=DLE"); + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} fallback logoURI initialized`); + } catch (fallbackError) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} fallback logoURI also failed: ${fallbackError.message}`); + } + } + + } catch (error) { + console.error(`[MULTI_DBG] chainId=${Number(net.chainId)} module deployment failed:`, error.message); + throw error; + } + + return modules; +} + +// Деплой модулей во всех сетях +async function deployModulesInAllNetworks(networks, pk, dleAddress) { + const moduleResults = []; + + for (let i = 0; i < networks.length; i++) { + const rpcUrl = networks[i]; + console.log(`[MULTI_DBG] deploying modules to network ${i + 1}/${networks.length}: ${rpcUrl}`); + + try { + const modules = await deployModulesInNetwork(rpcUrl, pk, dleAddress); + moduleResults.push(modules); + } catch (error) { + console.error(`[MULTI_DBG] Failed to deploy modules in network ${i + 1}:`, error.message); + moduleResults.push({ error: error.message }); + } + } + + return moduleResults; +} + +// Верификация контрактов в одной сети +async function verifyContractsInNetwork(rpcUrl, pk, dleAddress, modules, params) { + const { ethers } = hre; + const provider = new ethers.JsonRpcProvider(rpcUrl); + const wallet = new ethers.Wallet(pk, provider); + const net = await provider.getNetwork(); + + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} starting verification...`); + + const verification = {}; + + try { + // Верификация DLE + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} verifying DLE...`); + await hre.run("verify:verify", { + address: dleAddress, + constructorArguments: [ + { + name: params.name || '', + symbol: params.symbol || '', + location: params.location || '', + coordinates: params.coordinates || '', + jurisdiction: params.jurisdiction || 0, + oktmo: params.oktmo || '', + okvedCodes: params.okvedCodes || [], + kpp: params.kpp ? BigInt(params.kpp) : 0n, + quorumPercentage: params.quorumPercentage || 51, + initialPartners: params.initialPartners || [], + initialAmounts: (params.initialAmounts || []).map(amount => BigInt(amount)), + supportedChainIds: (params.supportedChainIds || []).map(id => BigInt(id)) + }, + BigInt(params.currentChainId || params.supportedChainIds?.[0] || 1), + params.initializer || params.initialPartners?.[0] || "0x0000000000000000000000000000000000000000" + ], + }); + verification.dle = 'success'; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} DLE verification successful`); + } catch (error) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} DLE verification failed: ${error.message}`); + verification.dle = 'failed'; + } + + // Верификация модулей + if (modules && !modules.error) { + try { + // Верификация TreasuryModule + if (modules.treasuryModule) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} verifying TreasuryModule...`); + await hre.run("verify:verify", { + address: modules.treasuryModule, + constructorArguments: [ + dleAddress, // _dleContract + Number(net.chainId), // _chainId + wallet.address // _emergencyAdmin + ], + }); + verification.treasuryModule = 'success'; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} TreasuryModule verification successful`); + } + } catch (error) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} TreasuryModule verification failed: ${error.message}`); + verification.treasuryModule = 'failed'; + } + + try { + // Верификация TimelockModule + if (modules.timelockModule) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} verifying TimelockModule...`); + await hre.run("verify:verify", { + address: modules.timelockModule, + constructorArguments: [ + dleAddress // _dleContract + ], + }); + verification.timelockModule = 'success'; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} TimelockModule verification successful`); + } + } catch (error) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} TimelockModule verification failed: ${error.message}`); + verification.timelockModule = 'failed'; + } + + try { + // Верификация DLEReader + if (modules.dleReader) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} verifying DLEReader...`); + await hre.run("verify:verify", { + address: modules.dleReader, + constructorArguments: [ + dleAddress // _dleContract + ], + }); + verification.dleReader = 'success'; + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} DLEReader verification successful`); + } + } catch (error) { + console.log(`[MULTI_DBG] chainId=${Number(net.chainId)} DLEReader verification failed: ${error.message}`); + verification.dleReader = 'failed'; + } + } + + return verification; +} + +// Верификация контрактов во всех сетях +async function verifyContractsInAllNetworks(networks, pk, dleAddress, moduleResults, params) { + const verificationResults = []; + + for (let i = 0; i < networks.length; i++) { + const rpcUrl = networks[i]; + console.log(`[MULTI_DBG] verifying contracts in network ${i + 1}/${networks.length}: ${rpcUrl}`); + + try { + const verification = await verifyContractsInNetwork(rpcUrl, pk, dleAddress, moduleResults[i], params); + verificationResults.push(verification); + } catch (error) { + console.error(`[MULTI_DBG] Failed to verify contracts in network ${i + 1}:`, error.message); + verificationResults.push({ error: error.message }); + } + } + + return verificationResults; +} + async function main() { const { ethers } = hre; @@ -258,7 +482,41 @@ async function main() { } console.log('[MULTI_DBG] SUCCESS: All DLE addresses are identical:', uniqueAddresses[0]); - console.log('MULTICHAIN_DEPLOY_RESULT', JSON.stringify(results)); + + // Деплой модулей во всех сетях + console.log('[MULTI_DBG] Starting module deployment...'); + const moduleResults = await deployModulesInAllNetworks(networks, pk, uniqueAddresses[0]); + + // Верификация контрактов + console.log('[MULTI_DBG] Starting contract verification...'); + const verificationResults = await verifyContractsInAllNetworks(networks, pk, uniqueAddresses[0], moduleResults, params); + + // Объединяем результаты + const finalResults = results.map((result, index) => ({ + ...result, + modules: moduleResults[index] || {}, + verification: verificationResults[index] || {} + })); + + console.log('MULTICHAIN_DEPLOY_RESULT', JSON.stringify(finalResults)); + + // Сохраняем информацию о модулях в отдельный файл для каждого DLE + const modulesInfo = { + dleAddress: uniqueAddresses[0], + modules: moduleResults, + verification: verificationResults, + deployTimestamp: new Date().toISOString() + }; + + // Создаем директорию temp если её нет + const tempDir = path.join(__dirname, '../temp'); + if (!fs.existsSync(tempDir)) { + fs.mkdirSync(tempDir, { recursive: true }); + } + + const deployResultPath = path.join(tempDir, `modules-${uniqueAddresses[0].toLowerCase()}.json`); + fs.writeFileSync(deployResultPath, JSON.stringify(modulesInfo, null, 2)); + console.log(`[MULTI_DBG] Modules info saved to: ${deployResultPath}`); } main().catch((e) => { console.error(e); process.exit(1); }); diff --git a/backend/services/dleV2Service.js b/backend/services/dleV2Service.js index 876d1fd..3dd2cb3 100644 --- a/backend/services/dleV2Service.js +++ b/backend/services/dleV2Service.js @@ -458,6 +458,18 @@ class DLEV2Service { deployParams.currentChainId = 1; // По умолчанию Ethereum } + // Обрабатываем logoURI + if (deployParams.logoURI) { + // Если logoURI относительный путь, делаем его абсолютным + if (deployParams.logoURI.startsWith('/uploads/')) { + deployParams.logoURI = `http://localhost:3000${deployParams.logoURI}`; + } + // Если это placeholder, оставляем как есть + if (deployParams.logoURI.includes('placeholder.com')) { + // Оставляем как есть + } + } + return deployParams; } @@ -573,8 +585,24 @@ class DLEV2Service { const resultMatch = stdout.match(/MULTICHAIN_DEPLOY_RESULT\s+(\[.*\])/); if (resultMatch) { - const result = JSON.parse(resultMatch[1]); - resolve(result); + const deployResults = JSON.parse(resultMatch[1]); + + // Преобразуем результат в нужный формат + const addresses = deployResults.map(r => r.address); + const allSame = addresses.every(addr => addr.toLowerCase() === addresses[0].toLowerCase()); + + resolve({ + success: true, + data: { + dleAddress: addresses[0], + networks: deployResults.map((r, index) => ({ + chainId: r.chainId, + address: r.address, + success: true + })), + allSame + } + }); } else { // Fallback: ищем адреса DLE в выводе по новому формату const dleAddressMatches = stdout.match(/\[MULTI_DBG\] chainId=\d+ DLE deployed at=(0x[a-fA-F0-9]{40})/g); diff --git a/frontend/public/dle-logo.png b/frontend/public/dle-logo.png new file mode 100644 index 0000000..e1223b9 --- /dev/null +++ b/frontend/public/dle-logo.png @@ -0,0 +1,3 @@ +# Это placeholder для логотипа DLE +# В реальном проекте здесь должен быть PNG файл с логотипом +# Размер рекомендуется: 200x200 пикселей diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico deleted file mode 100755 index a759494..0000000 Binary files a/frontend/public/favicon.ico and /dev/null differ diff --git a/frontend/public/uploads/logos/default-token.svg b/frontend/public/uploads/logos/default-token.svg new file mode 100644 index 0000000..f7c789f --- /dev/null +++ b/frontend/public/uploads/logos/default-token.svg @@ -0,0 +1,20 @@ + diff --git a/frontend/src/views/ManagementView.vue b/frontend/src/views/ManagementView.vue index 10f529d..60b1892 100644 --- a/frontend/src/views/ManagementView.vue +++ b/frontend/src/views/ManagementView.vue @@ -58,8 +58,20 @@ @click="selectDle(dle)" >