@@ -16,6 +16,7 @@ const fs = require('fs');
const { ethers } = require ( 'ethers' ) ;
const logger = require ( '../utils/logger' ) ;
const { getRpcUrlByChainId } = require ( './rpcProviderService' ) ;
const deploymentTracker = require ( '../utils/deploymentTracker' ) ;
const etherscanV2 = require ( './etherscanV2VerificationService' ) ;
const verificationStore = require ( './verificationStore' ) ;
@@ -29,11 +30,18 @@ class DLEV2Service {
* @param {Object} dleParams - Параметры DLE
* @returns {Promise<Object>} - Результат создания DLE
*/
async createDLE ( dleParams ) {
async createDLE ( dleParams , deploymentId = null ) {
console . log ( "🔥 [DLEV2-SERVICE] ФУНКЦИЯ createDLE ВЫЗВАНА!" ) ;
logger . info ( "🚀 DEBUG: ВХОДИМ В createDLE ФУНКЦИЮ" ) ;
let paramsFile = null ;
let tempParamsFile = null ;
try {
logger . info ( 'Начало создания DLE v2 с параметрами:' , dleParams ) ;
// WebSocket обновление: начало процесса
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Валидация параметров' , 5 , 'Проверяем входные данные' ) ;
}
// Валидация входных данных
this . validateDLEParams ( dleParams ) ;
@@ -50,6 +58,11 @@ class DLEV2Service {
logger . warn ( 'Н е удалось вычислить initializerAddress из приватного ключа:' , e . message ) ;
}
// WebSocket обновление: генерация CREATE2_SALT
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Генерация CREATE2 SALT' , 10 , 'Создаем уникальный идентификатор для детерминированного адреса' ) ;
}
// Генерируем одноразовый CREATE2_SALT и сохраняем е г о с уникальным ключом в secrets
const { createAndStoreNewCreate2Salt } = require ( './secretStore' ) ;
const { salt : create2Salt , key : saltKey } = await createAndStoreNewCreate2Salt ( { label : deployParams . name || 'DLEv2' } ) ;
@@ -66,6 +79,11 @@ class DLEV2Service {
}
fs . copyFileSync ( paramsFile , tempParamsFile ) ;
// WebSocket обновление: поиск RPC URLs
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Поиск RPC endpoints' , 15 , 'Подключаемся к блокчейн сетям' ) ;
}
// Готовим RPC для всех выбранных сетей
const rpcUrls = [ ] ;
for ( const cid of deployParams . supportedChainIds ) {
@@ -99,14 +117,7 @@ class DLEV2Service {
const walletAddress = new ethers . Wallet ( pk , provider ) . address ;
const balance = await provider . getBalance ( walletAddress ) ;
if ( typeof ethers . parseEther !== 'function' ) {
throw new Error ( 'Метод ethers.parseEther не найден' ) ;
}
const minBalance = ethers . parseEther ( "0.00001" ) ;
if ( typeof ethers . formatEther !== 'function' ) {
throw new Error ( 'Метод ethers.formatEther не найден' ) ;
}
logger . info ( ` Баланс кошелька ${ walletAddress } : ${ ethers . formatEther ( balance ) } ETH ` ) ;
if ( balance < minBalance ) {
throw new Error ( ` Недостаточно ETH для деплоя в ${ deployParams . supportedChainIds [ 0 ] } . Баланс: ${ ethers . formatEther ( balance ) } ETH ` ) ;
@@ -117,27 +128,87 @@ class DLEV2Service {
throw new Error ( 'Приватный ключ для деплоя не передан' ) ;
}
// Рассчитываем INIT_CODE_HASH автоматически из актуального initCode
const initCodeHash = await this . computeInitCodeHash ( {
... deployParams ,
currentChainId : deployParams . currentChainId || deployParams . supportedChainIds [ 0 ]
} ) ;
// Сохраняем ключ Etherscan V2 ПЕРЕД деплоем
logger . info ( ` 🔑 Etherscan API Key получен: ${ dleParams . etherscanApiKey ? '[Е С Т Ь ]' : '[Н Е Т ]' } ` ) ;
try {
if ( dleParams . etherscanApiKey ) {
logger . info ( '🔑 Сохраняем Etherscan API Key в secretStore...' ) ;
const { setSecret } = require ( './secretStore' ) ;
await setSecret ( 'ETHERSCAN_V2_API_KEY' , dleParams . etherscanApiKey ) ;
logger . info ( '🔑 Etherscan API Key успешно сохранен в базу данных' ) ;
} else {
logger . warn ( '🔑 Etherscan API Key не передан, пропускаем сохранение' ) ;
}
} catch ( e ) {
logger . error ( '🔑 Ошибка при сохранении Etherscan API Key:' , e . message ) ;
}
// WebSocket обновление: компиляция произойдет автоматически в deploy-multichain.js
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Подготовка к деплою' , 25 , 'Подготавливаем параметры для деплоя' ) ;
}
// INIT_CODE_HASH будет вычислен в deploy-multichain.js
// Factory больше не используется - деплой DLE напрямую
logger . info ( ` Подготовка к прямому деплою DLE в сетях: ${ deployParams . supportedChainIds . join ( ', ' ) } ` ) ;
// WebSocket обновление: начало мульти-чейн деплоя
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Мульти-чейн деплой' , 40 ) ;
deploymentTracker . addLog ( deploymentId , ` 🌐 Деплой в ${ deployParams . supportedChainIds . length } сетях: ${ deployParams . supportedChainIds . join ( ', ' ) } ` , 'info' ) ;
deploymentTracker . addLog ( deploymentId , ` 📋 Этапы: 1) DLE контракт → 2) Модули → 3) Инициализация → 4) Верификация ` , 'info' ) ;
}
// Мультисетевой деплой одним вызовом
logger . info ( 'Запуск мульти-чейн деплоя...' ) ;
logger . info ( "🔍 DEBUG: Подготовка к прямому деплою..." ) ;
const result = await this . runDeployMultichain ( paramsFile , {
rpcUrls : rpcUrls ,
chainIds : deployParams . supportedChainIds ,
privateKey : dleParams . privateKey ? . startsWith ( '0x' ) ? dleParams . privateKey : ` 0x ${ dleParams . privateKey } ` ,
salt : create2Salt ,
initCodeHash
etherscanApiKey : dleParams . etherscanApiKey
} ) ;
logger . info ( 'Деплой завершен, результат:' , JSON . stringify ( result , null , 2 ) ) ;
logger . info ( "🔍 DEBUG: Запуск мультисетевого деплоя..." ) ;
// WebSocket обновление: деплой завершен, начинаем обработку результатов
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Обработка результатов' , 85 , 'Деплой завершен, сохраняем результаты' ) ;
deploymentTracker . addLog ( deploymentId , ` ✅ DLE контракт задеплоен в ${ result . networks ? . length || 0 } сетях ` , 'success' ) ;
if ( result . networks ) {
result . networks . forEach ( network => {
deploymentTracker . addLog ( deploymentId , ` 📍 ${ network . networkName || ` Chain ${ network . chainId } ` } : ${ network . address } ` , 'info' ) ;
} ) ;
}
// Логируем информацию о модулях
if ( result . modules ) {
deploymentTracker . addLog ( deploymentId , ` 🔧 Модули задеплоены в ${ result . modules . length } сетях ` , 'info' ) ;
result . modules . forEach ( ( moduleSet , index ) => {
if ( moduleSet && ! moduleSet . error ) {
deploymentTracker . addLog ( deploymentId , ` 📦 Сеть ${ index + 1 } : Treasury= ${ moduleSet . treasuryModule ? . substring ( 0 , 10 ) } ..., Timelock= ${ moduleSet . timelockModule ? . substring ( 0 , 10 ) } ..., Reader= ${ moduleSet . dleReader ? . substring ( 0 , 10 ) } ... ` , 'info' ) ;
}
} ) ;
}
// Логируем информацию о верификации
if ( result . verification ) {
deploymentTracker . addLog ( deploymentId , ` 🔍 Верификация выполнена в ${ result . verification . length } сетях ` , 'info' ) ;
result . verification . forEach ( ( verification , index ) => {
if ( verification && ! verification . error ) {
const dleStatus = verification . dle === 'success' ? '✅' : '❌' ;
const treasuryStatus = verification . treasuryModule === 'success' ? '✅' : '❌' ;
const timelockStatus = verification . timelockModule === 'success' ? '✅' : '❌' ;
const readerStatus = verification . dleReader === 'success' ? '✅' : '❌' ;
deploymentTracker . addLog ( deploymentId , ` 🔍 Сеть ${ index + 1 } : DLE ${ dleStatus } Treasury ${ treasuryStatus } Timelock ${ timelockStatus } Reader ${ readerStatus } ` , 'info' ) ;
}
} ) ;
}
}
// Сохраняем информацию о созданном DLE для отображения на странице управления
try {
@@ -148,6 +219,7 @@ class DLEV2Service {
logger . error ( 'Неверная структура результата деплоя:' , result ) ;
throw new Error ( 'Неверная структура результата деплоя' ) ;
}
logger . info ( "🔍 DEBUG: Вызываем runDeployMultichain..." ) ;
// Если результат - массив (прямой результат из скрипта), преобразуем е г о
let deployResult = result ;
@@ -209,6 +281,14 @@ class DLEV2Service {
fs . writeFileSync ( savedPath , JSON . stringify ( dleData , null , 2 ) ) ;
// logger.info(`DLE данные сохранены в: ${savedPath}`); // Убрано избыточное логирование
// WebSocket обновление: финализация
if ( deploymentId ) {
deploymentTracker . updateProgress ( deploymentId , 'Завершение' , 100 , 'Деплой успешно завершен!' ) ;
deploymentTracker . addLog ( deploymentId , ` 🎉 DLE ${ result . data . name } ( ${ result . data . symbol } ) успешно создан! ` , 'success' ) ;
deploymentTracker . addLog ( deploymentId , ` 📊 Партнеров: ${ result . data . partnerBalances ? . length || 0 } ` , 'info' ) ;
deploymentTracker . addLog ( deploymentId , ` 💰 Общий supply: ${ result . data . totalSupply || 'N/A' } ` , 'info' ) ;
}
return {
success : true ,
data : dleData
@@ -220,31 +300,25 @@ class DLEV2Service {
logger . warn ( 'Н е удалось сохранить локальную карточку DLE:' , e . message ) ;
}
// Сохраняем ключ Etherscan V2 для последующих авто‑обновлений статуса, если он передан
try {
if ( dleParams . etherscanApiKey ) {
const { setSecret } = require ( './secretStore' ) ;
await setSecret ( 'ETHERSCAN_V2_API_KEY' , dleParams . etherscanApiKey ) ;
}
} catch ( _ ) { }
// Etherscan API Key уже сохранен в начале функции
// Авто-в ерификация через Etherscan V2 (опционально)
if ( dleParams . autoVerifyAfterDeploy ) {
try {
await this . autoVerifyAcrossChains ( {
deployParams ,
deployResult : result ,
apiKey : dleParams . etherscanApiKey
} ) ;
} catch ( e ) {
logger . warn ( 'Авто-верификация завершилась с ошибкой:' , e . message ) ;
}
// В ерификация выполняется в deploy-multichain.js
// WebSocket обновление: деплой успешно завершен
if ( deploymentId ) {
deploymentTracker . completeDeployment ( deploymentId , result ) ;
}
return result ;
} catch ( error ) {
logger . error ( 'Ошибка при создании DLE v2:' , error ) ;
// WebSocket обновление: деплой завершился с ошибкой
if ( deploymentId ) {
deploymentTracker . failDeployment ( deploymentId , error ) ;
}
throw error ;
} finally {
try {
@@ -423,9 +497,6 @@ class DLEV2Service {
// Принимаем как строки, так и числа; конвертируем в base units (18 знаков)
try {
if ( typeof rawAmount === 'number' && Number . isFinite ( rawAmount ) ) {
if ( typeof ethers . parseUnits !== 'function' ) {
throw new Error ( 'Метод ethers.parseUnits не найден' ) ;
}
return ethers . parseUnits ( rawAmount . toString ( ) , 18 ) . toString ( ) ;
}
if ( typeof rawAmount === 'string' ) {
@@ -435,9 +506,6 @@ class DLEV2Service {
return BigInt ( a ) . toString ( ) ;
}
// Десятичная строка — конвертируем в base units
if ( typeof ethers . parseUnits !== 'function' ) {
throw new Error ( 'Метод ethers.parseUnits не найден' ) ;
}
return ethers . parseUnits ( a , 18 ) . toString ( ) ;
}
// BigInt или иные типы — приводим к строке без изменения масштаба
@@ -530,7 +598,7 @@ class DLEV2Service {
const hardhatProcess = spawn ( 'npx' , [ 'hardhat' , 'run' , scriptPath ] , {
cwd : path . join ( _ _dirname , '..' ) ,
env : envVars ,
stdio : 'pipe'
stdio : [ 'inherit' , 'pipe' , 'pipe' ]
} ) ;
let stdout = '' ;
@@ -575,13 +643,19 @@ class DLEV2Service {
const envVars = {
... process . env ,
PRIVATE _KEY : opts . privateKey
PRIVATE _KEY : opts . privateKey ,
ETHERSCAN _API _KEY : opts . etherscanApiKey || ''
} ;
logger . info ( ` 🔑 Передаем в deploy-multichain.js: ETHERSCAN_API_KEY= ${ opts . etherscanApiKey ? '[Е С Т Ь ]' : '[Н Е Т ]' } ` ) ;
logger . info ( ` 🔑 Передаем в deploy-multichain.js: PRIVATE_KEY= ${ opts . privateKey ? '[Е С Т Ь ]' : '[Н Е Т ]' } ` ) ;
logger . info ( ` 🔑 PRIVATE_KEY длина: ${ opts . privateKey ? opts . privateKey . length : 0 } ` ) ;
logger . info ( ` 🔑 PRIVATE_KEY значение: ${ opts . privateKey ? opts . privateKey . substring ( 0 , 10 ) + '...' : 'undefined' } ` ) ;
const p = spawn ( 'npx' , [ 'hardhat' , 'run' , scriptPath ] , {
cwd : path . join ( _ _dirname , '..' ) ,
env : envVars ,
stdio : 'pipe'
stdio : [ 'inherit' , 'pipe' , 'pipe' ]
} ) ;
let stdout = '' , stderr = '' ;
@@ -838,11 +912,11 @@ class DLEV2Service {
// Преобразуем группы в массив
return Array . from ( groups . values ( ) ) . map ( group => ( {
... group ,
// Основной адрес DLE (из первой сети)
dleAddress : group . networks [ 0 ] ? . dleAddress ,
... group ,
// Основной адрес DLE (из первой сети)
dleAddress : group . networks [ 0 ] ? . dleAddress ,
// Общее количество сетей
totalNetworks : group . networks . length ,
totalNetworks : group . networks . length ,
// Поддерживаемые сети
supportedChainIds : group . networks . map ( n => n . chainId )
} ) ) ;
@@ -894,96 +968,6 @@ class DLEV2Service {
}
}
// Авто-расчёт INIT_CODE_HASH
async computeInitCodeHash ( params ) {
try {
// Проверяем наличие обязательных параметров
if ( ! params . name || ! params . symbol || ! params . location ) {
throw new Error ( 'Отсутствуют обязательные параметры для вычисления INIT_CODE_HASH' ) ;
}
const hre = require ( 'hardhat' ) ;
const { ethers } = hre ;
// Проверяем, что контракт DLE существует
try {
const DLE = await hre . ethers . getContractFactory ( 'DLE' ) ;
if ( ! DLE ) {
throw new Error ( 'Контракт DLE не найден в Hardhat' ) ;
}
} catch ( contractError ) {
throw new Error ( ` Ошибка загрузки контракта DLE: ${ contractError . message } ` ) ;
}
const DLE = await hre . ethers . getContractFactory ( 'DLE' ) ;
const dleConfig = {
name : params . name ,
symbol : params . symbol ,
location : params . location ,
coordinates : params . coordinates || "" ,
jurisdiction : params . jurisdiction || 1 ,
okvedCodes : params . okvedCodes || [ ] ,
kpp : params . kpp || 0 ,
quorumPercentage : params . quorumPercentage || 51 ,
initialPartners : params . initialPartners || [ ] ,
initialAmounts : params . initialAmounts || [ ] ,
supportedChainIds : params . supportedChainIds || [ 1 ]
} ;
// Учитываем актуальную сигнатуру конструктора: (dleConfig, currentChainId, initializer)
const initializer = params . initializerAddress || "0x0000000000000000000000000000000000000000" ;
const currentChainId = params . currentChainId || 1 ; // Fallback на Ethereum mainnet
logger . info ( 'Вычисление INIT_CODE_HASH с параметрами:' , {
name : dleConfig . name ,
symbol : dleConfig . symbol ,
currentChainId ,
initializer
} ) ;
// Проверяем, что метод getDeployTransaction существует
if ( typeof DLE . getDeployTransaction !== 'function' ) {
throw new Error ( 'Метод getDeployTransaction не найден в контракте DLE' ) ;
}
const deployTx = await DLE . getDeployTransaction ( dleConfig , currentChainId , initializer ) ;
if ( ! deployTx || ! deployTx . data ) {
throw new Error ( 'Н е удалось получить данные транзакции деплоя' ) ;
}
const initCode = deployTx . data ;
// Проверяем, что метод keccak256 существует
if ( typeof ethers . keccak256 !== 'function' ) {
throw new Error ( 'Метод ethers.keccak256 не найден' ) ;
}
const hash = ethers . keccak256 ( initCode ) ;
logger . info ( 'INIT_CODE_HASH вычислен успешно:' , hash ) ;
return hash ;
} catch ( error ) {
logger . error ( 'Ошибка при вычислении INIT_CODE_HASH:' , error ) ;
// Fallback: возвращаем хеш на основе параметров
const { ethers } = require ( 'ethers' ) ;
const fallbackData = JSON . stringify ( {
name : params . name ,
symbol : params . symbol ,
location : params . location ,
jurisdiction : params . jurisdiction ,
supportedChainIds : params . supportedChainIds
} ) ;
// Проверяем, что методы существуют
if ( typeof ethers . toUtf8Bytes !== 'function' ) {
throw new Error ( 'Метод ethers.toUtf8Bytes не найден' ) ;
}
if ( typeof ethers . keccak256 !== 'function' ) {
throw new Error ( 'Метод ethers.keccak256 не найден' ) ;
}
return ethers . keccak256 ( ethers . toUtf8Bytes ( fallbackData ) ) ;
}
}
@@ -1017,14 +1001,7 @@ class DLEV2Service {
const wallet = new ethers . Wallet ( privateKey , provider ) ;
const balance = await provider . getBalance ( wallet . address ) ;
if ( typeof ethers . formatEther !== 'function' ) {
throw new Error ( 'Метод ethers.formatEther не найден' ) ;
}
const balanceEth = ethers . formatEther ( balance ) ;
if ( typeof ethers . parseEther !== 'function' ) {
throw new Error ( 'Метод ethers.parseEther не найден' ) ;
}
const minBalance = ethers . parseEther ( "0.001" ) ;
const ok = balance >= minBalance ;
@@ -1057,155 +1034,7 @@ class DLEV2Service {
} ;
}
/**
* Авто-верификация контракта во всех выбранных сетях через Etherscan V2
* @param {Object} args
* @param {Object} args.deployParams
* @param {Object} args.deployResult - { success, data: { dleAddress, networks: [{rpcUrl,address}] } }
* @param {string} [args.apiKey]
*/
async autoVerifyAcrossChains ( { deployParams , deployResult , apiKey } ) {
if ( ! deployResult ? . success ) throw new Error ( 'Нет результата деплоя для верификации' ) ;
// Подхватить ключ из secrets, если аргумент не передан
if ( ! apiKey ) {
try {
const { getSecret } = require ( './secretStore' ) ;
apiKey = await getSecret ( 'ETHERSCAN_V2_API_KEY' ) ;
} catch ( _ ) { }
}
// Получаем компилер, standard-json-input и contractName из artifacts/build-info
const { standardJson , compilerVersion , contractName , constructorArgsHex } = await this . prepareVerificationPayload ( deployParams ) ;
// Для каждой сети отправим верификацию, используя адрес из результата для соответствующего chainId
const chainIds = Array . isArray ( deployParams . supportedChainIds ) ? deployParams . supportedChainIds : [ ] ;
const netMap = new Map ( ) ;
if ( Array . isArray ( deployResult . data ? . networks ) ) {
for ( const n of deployResult . data . networks ) {
if ( n && typeof n . chainId === 'number' ) netMap . set ( n . chainId , n . address ) ;
}
}
for ( const cid of chainIds ) {
try {
const addrForChain = netMap . get ( cid ) ;
if ( ! addrForChain ) {
logger . warn ( ` [AutoVerify] Нет адреса для chainId= ${ cid } в результате деплоя, пропускаю ` ) ;
continue ;
}
const guid = await etherscanV2 . submitVerification ( {
chainId : cid ,
contractAddress : addrForChain ,
contractName ,
compilerVersion ,
standardJsonInput : standardJson ,
constructorArgsHex ,
apiKey
} ) ;
logger . info ( ` [AutoVerify] Отправлена верификация в chainId= ${ cid } , guid= ${ guid } ` ) ;
verificationStore . updateChain ( addrForChain , cid , { guid , status : 'submitted' } ) ;
} catch ( e ) {
logger . warn ( ` [AutoVerify] Ошибка отправки верификации для chainId= ${ cid } : ${ e . message } ` ) ;
const addrForChain = netMap . get ( cid ) || 'unknown' ;
verificationStore . updateChain ( addrForChain , cid , { status : ` error: ${ e . message } ` } ) ;
}
}
}
/**
* Формирует стандартный JSON input, compilerVersion, contractName и ABI-кодированные аргументы конструктора
*/
async prepareVerificationPayload ( params ) {
const hre = require ( 'hardhat' ) ;
const path = require ( 'path' ) ;
const fs = require ( 'fs' ) ;
// 1) Найти самый свежий build-info
const buildInfoDir = path . join ( _ _dirname , '..' , 'artifacts' , 'build-info' ) ;
let latestFile = null ;
try {
const entries = fs . readdirSync ( buildInfoDir ) . filter ( f => f . endsWith ( '.json' ) ) ;
let bestMtime = 0 ;
for ( const f of entries ) {
const fp = path . join ( buildInfoDir , f ) ;
const st = fs . statSync ( fp ) ;
if ( st . mtimeMs > bestMtime ) { bestMtime = st . mtimeMs ; latestFile = fp ; }
}
} catch ( e ) {
logger . warn ( 'Артефакты build-info не найдены:' , e . message ) ;
}
let standardJson = null ;
let compilerVersion = null ;
let sourcePathForDLE = 'contracts/DLE.sol' ;
let contractName = 'contracts/DLE.sol:DLE' ;
if ( latestFile ) {
try {
const buildInfo = JSON . parse ( fs . readFileSync ( latestFile , 'utf8' ) ) ;
// input — это стандартный JSON input для solc
standardJson = buildInfo . input || null ;
// Версия компилятора
const long = buildInfo . solcLongVersion || buildInfo . solcVersion || hre . config . solidity ? . version ;
compilerVersion = long ? ( long . startsWith ( 'v' ) ? long : ` v ${ long } ` ) : undefined ;
// Найти путь контракта DLE
if ( buildInfo . output && buildInfo . output . contracts ) {
for ( const [ filePathKey , contractsMap ] of Object . entries ( buildInfo . output . contracts ) ) {
if ( contractsMap && contractsMap [ 'DLE' ] ) {
sourcePathForDLE = filePathKey ;
contractName = ` ${ filePathKey } :DLE ` ;
break ;
}
}
}
} catch ( e ) {
logger . warn ( 'Н е удалось прочитать build-info:' , e . message ) ;
}
}
// Если не нашли — fallback на config
if ( ! compilerVersion ) compilerVersion = ` v ${ hre . config . solidity . compilers ? . [ 0 ] ? . version || hre . config . solidity . version } ` ;
if ( ! standardJson ) {
// fallback минимальная структура
standardJson = {
language : 'Solidity' ,
sources : { [ sourcePathForDLE ] : { content : '' } } ,
settings : { optimizer : { enabled : true , runs : 200 } }
} ;
}
// 2) Посчитать ABI-код аргументов конструктора через сравнение с bytecode
// Конструктор: (dleConfig, currentChainId, initializer)
const Factory = await hre . ethers . getContractFactory ( 'DLE' ) ;
const dleConfig = {
name : params . name ,
symbol : params . symbol ,
location : params . location ,
coordinates : params . coordinates ,
jurisdiction : params . jurisdiction ,
okvedCodes : params . okvedCodes || [ ] ,
kpp : params . kpp ,
quorumPercentage : params . quorumPercentage ,
initialPartners : params . initialPartners ,
initialAmounts : params . initialAmounts ,
supportedChainIds : params . supportedChainIds
} ;
const initializer = params . initialPartners ? . [ 0 ] || "0x0000000000000000000000000000000000000000" ;
const deployTx = await Factory . getDeployTransaction ( dleConfig , params . currentChainId , initializer ) ;
const fullData = deployTx . data ; // 0x + creation bytecode + encoded args
const bytecode = Factory . bytecode ; // 0x + creation bytecode
let constructorArgsHex ;
try {
if ( fullData && bytecode && fullData . startsWith ( bytecode ) ) {
constructorArgsHex = '0x' + fullData . slice ( bytecode . length ) ;
}
} catch ( e ) {
logger . warn ( 'Н е удалось выделить constructorArguments из deployTx.data:' , e . message ) ;
}
return { standardJson , compilerVersion , contractName , constructorArgsHex } ;
}
}
module . exports = new DLEV2Service ( ) ;