/** * Copyright (c) 2024-2026 Тарабанов Александр Викторович * All rights reserved. * * This software is proprietary and confidential. * Unauthorized copying, modification, or distribution is prohibited. * * For licensing inquiries: info@hb3-accelerator.com * Website: https://hb3-accelerator.com * GitHub: https://github.com/VC-HB3-Accelerator */ import { ref, computed } from 'vue'; import { ethers } from 'ethers'; import { DLE_ABI, TOKEN_ABI } from '@/utils/dle-abi'; /** * Композабл для работы с DLE смарт-контрактом * Содержит правильные ABI и функции для взаимодействия с контрактом */ export function useDleContract() { // Состояние const isConnected = ref(false); const provider = ref(null); const signer = ref(null); const contract = ref(null); const userAddress = ref(null); const chainId = ref(null); // Используем общий ABI из utils/dle-abi.js /** * Подключиться к кошельку */ const connectWallet = async () => { try { if (!window.ethereum) { throw new Error('MetaMask не найден. Пожалуйста, установите MetaMask.'); } // Запрашиваем подключение const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); // Создаем провайдер и подписанта provider.value = new ethers.BrowserProvider(window.ethereum); signer.value = await provider.value.getSigner(); userAddress.value = await signer.value.getAddress(); // Получаем информацию о сети const network = await provider.value.getNetwork(); chainId.value = Number(network.chainId); isConnected.value = true; console.log('✅ Кошелек подключен:', { address: userAddress.value, chainId: chainId.value, network: network.name }); return { success: true, address: userAddress.value, chainId: chainId.value }; } catch (error) { console.error('❌ Ошибка подключения к кошельку:', error); isConnected.value = false; throw error; } }; /** * Инициализировать контракт */ const initContract = (contractAddress) => { if (!provider.value) { throw new Error('Провайдер не инициализирован. Сначала подключите кошелек.'); } contract.value = new ethers.Contract(contractAddress, DLE_ABI, signer.value); console.log('✅ DLE контракт инициализирован:', contractAddress); }; /** * Проверить баланс токенов пользователя */ const checkTokenBalance = async (contractAddress) => { try { if (!contract.value) { initContract(contractAddress); } const balance = await contract.value.balanceOf(userAddress.value); const balanceFormatted = ethers.formatEther(balance); console.log(`💰 Баланс токенов: ${balanceFormatted}`); return { success: true, balance: balanceFormatted, hasTokens: balance > 0 }; } catch (error) { console.error('❌ Ошибка проверки баланса:', error); return { success: false, error: error.message, balance: '0', hasTokens: false }; } }; /** * Голосовать за предложение */ const voteOnProposal = async (contractAddress, proposalId, support) => { try { if (!contract.value) { initContract(contractAddress); } console.log('🗳️ Начинаем голосование:', { proposalId, support }); // Проверяем баланс токенов const balanceCheck = await checkTokenBalance(contractAddress); if (!balanceCheck.hasTokens) { throw new Error('У вас нет токенов для голосования'); } // Отправляем транзакцию голосования const tx = await contract.value.vote(proposalId, support); console.log('📤 Транзакция отправлена:', tx.hash); // Ждем подтверждения const receipt = await tx.wait(); console.log('✅ Голосование успешно:', receipt); return { success: true, transactionHash: tx.hash, receipt: receipt }; } catch (error) { console.error('❌ Ошибка голосования:', error); // Улучшенная обработка ошибок let errorMessage = error.message; if (error.message.includes('execution reverted')) { errorMessage = 'Транзакция отклонена смарт-контрактом. Возможные причины:\n' + '• Предложение уже не активно\n' + '• Вы уже голосовали за это предложение\n' + '• Недостаточно прав для голосования\n' + '• Предложение не существует'; } else if (error.message.includes('user rejected')) { errorMessage = 'Транзакция отклонена пользователем'; } else if (error.message.includes('insufficient funds')) { errorMessage = 'Недостаточно средств для оплаты газа'; } return { success: false, error: errorMessage, originalError: error }; } }; /** * Исполнить предложение */ const executeProposal = async (contractAddress, proposalId) => { try { if (!contract.value) { initContract(contractAddress); } console.log('⚡ Исполняем предложение:', proposalId); const tx = await contract.value.executeProposal(proposalId); console.log('📤 Транзакция отправлена:', tx.hash); const receipt = await tx.wait(); console.log('✅ Предложение исполнено:', receipt); return { success: true, transactionHash: tx.hash, receipt: receipt }; } catch (error) { console.error('❌ Ошибка исполнения предложения:', error); return { success: false, error: error.message, originalError: error }; } }; /** * Отменить предложение */ const cancelProposal = async (contractAddress, proposalId, reason) => { try { if (!contract.value) { initContract(contractAddress); } console.log('❌ Отменяем предложение:', { proposalId, reason }); const tx = await contract.value.cancelProposal(proposalId, reason); console.log('📤 Транзакция отправлена:', tx.hash); const receipt = await tx.wait(); console.log('✅ Предложение отменено:', receipt); return { success: true, transactionHash: tx.hash, receipt: receipt }; } catch (error) { console.error('❌ Ошибка отмены предложения:', error); return { success: false, error: error.message, originalError: error }; } }; /** * Получить состояние предложения */ const getProposalState = async (contractAddress, proposalId) => { try { if (!contract.value) { initContract(contractAddress); } const state = await contract.value.getProposalState(proposalId); // 0=Pending, 1=Succeeded, 2=Defeated, 3=Executed, 4=Canceled, 5=ReadyForExecution const stateNames = { 0: 'Pending', 1: 'Succeeded', 2: 'Defeated', 3: 'Executed', 4: 'Canceled', 5: 'ReadyForExecution' }; return { success: true, state: state, stateName: stateNames[state] || 'Unknown' }; } catch (error) { console.error('❌ Ошибка получения состояния предложения:', error); return { success: false, error: error.message, state: null }; } }; /** * Проверить результат предложения */ const checkProposalResult = async (contractAddress, proposalId) => { try { if (!contract.value) { initContract(contractAddress); } const result = await contract.value.checkProposalResult(proposalId); return { success: true, passed: result.passed, quorumReached: result.quorumReached }; } catch (error) { console.error('❌ Ошибка проверки результата предложения:', error); return { success: false, error: error.message, passed: false, quorumReached: false }; } }; /** * Получить информацию о DLE */ const getDleInfo = async (contractAddress) => { try { if (!contract.value) { initContract(contractAddress); } const info = await contract.value.getDLEInfo(); return { success: true, data: { name: info.name, symbol: info.symbol, location: info.location, coordinates: info.coordinates, jurisdiction: info.jurisdiction, okvedCodes: info.okvedCodes, kpp: info.kpp, creationTimestamp: info.creationTimestamp, isActive: info.isActive } }; } catch (error) { console.error('❌ Ошибка получения информации о DLE:', error); return { success: false, error: error.message }; } }; // Вычисляемые свойства const isWalletConnected = computed(() => isConnected.value); const currentUserAddress = computed(() => userAddress.value); const currentChainId = computed(() => chainId.value); return { // Состояние isConnected, provider, signer, contract, userAddress, chainId, // Вычисляемые свойства isWalletConnected, currentUserAddress, currentChainId, // Методы connectWallet, initContract, checkTokenBalance, voteOnProposal, executeProposal, cancelProposal, getProposalState, checkProposalResult, getDleInfo }; }