import { ref, computed } from 'vue'; import axios from 'axios'; /** * Composable для работы с сетями блокчейн * Предоставляет списки доступных сетей, URL RPC и функции для работы с ними */ export default function useBlockchainNetworks() { // Группы сетей для отображения в интерфейсе const networkGroups = [ { label: 'Основные сети', options: [ { value: 'ethereum', label: 'Ethereum Mainnet', chainId: 1 }, { value: 'bsc', label: 'Binance Smart Chain', chainId: 56 }, { value: 'polygon', label: 'Polygon', chainId: 137 }, { value: 'arbitrum', label: 'Arbitrum One', chainId: 42161 }, { value: 'optimism', label: 'Optimism', chainId: 10 }, { value: 'avalanche', label: 'Avalanche C-Chain', chainId: 43114 }, { value: 'gnosis', label: 'Gnosis Chain (xDai)', chainId: 100 }, { value: 'celo', label: 'Celo', chainId: 42220 }, { value: 'fantom', label: 'Fantom Opera', chainId: 250 }, { value: 'harmony', label: 'Harmony', chainId: 1666600000 }, { value: 'metis', label: 'Metis Andromeda', chainId: 1088 }, { value: 'aurora', label: 'Aurora', chainId: 1313161554 }, { value: 'cronos', label: 'Cronos', chainId: 25 } ] }, { label: 'Тестовые сети', options: [ { value: 'sepolia', label: 'Sepolia (Ethereum testnet)', chainId: 11155111 }, { value: 'goerli', label: 'Goerli (Ethereum testnet)', chainId: 5 }, { value: 'holesky', label: 'Holesky (Ethereum testnet)', chainId: 17000 }, { value: 'bsc-testnet', label: 'BSC Testnet', chainId: 97 }, { value: 'mumbai', label: 'Mumbai (Polygon testnet)', chainId: 80001 }, { value: 'arbitrum-goerli', label: 'Arbitrum Goerli', chainId: 421613 }, { value: 'optimism-goerli', label: 'Optimism Goerli', chainId: 420 }, { value: 'avalanche-fuji', label: 'Avalanche Fuji', chainId: 43113 }, { value: 'fantom-testnet', label: 'Fantom Testnet', chainId: 4002 } ] }, { label: 'Локальные сети', options: [ { value: 'localhost', label: 'Localhost (Hardhat)', chainId: 31337 }, { value: 'ganache', label: 'Ganache', chainId: 1337 } ] }, { label: 'Другое', options: [ { value: 'custom', label: 'Другая сеть (ввести вручную)', chainId: null } ] } ]; // Создаем плоский список всех сетей для удобного использования в компонентах const networks = computed(() => { return networkGroups.flatMap(group => group.options); }); // Объект для хранения выбранной сети и пользовательских значений const networkEntry = ref({ networkId: '', rpcUrl: '', customNetworkId: '', customChainId: null }); // Функция для получения chainId по networkId const getChainIdByNetworkId = (networkId) => { for (const group of networkGroups) { const option = group.options.find(opt => opt.value === networkId); if (option) { return option.chainId; } } return null; }; // Функция для добавления новой конфигурации сети const validateAndPrepareNetworkConfig = () => { let networkId = networkEntry.value.networkId; const rpcUrl = networkEntry.value.rpcUrl.trim(); // Если выбрана опция "custom", используем пользовательский ID if (networkId === 'custom') { networkId = networkEntry.value.customNetworkId.trim(); if (!networkId) { return { valid: false, error: 'Пожалуйста, введите пользовательский ID сети' }; } } if (!networkId || !rpcUrl) { return { valid: false, error: 'Пожалуйста, выберите ID Сети и введите RPC URL' }; } // Определяем chainId let chainId = getChainIdByNetworkId(networkId); if (!chainId && networkId === networkEntry.value.customNetworkId) { chainId = networkEntry.value.customChainId; } return { valid: true, networkConfig: { networkId, rpcUrl, chainId } }; }; // Функция сброса формы const resetNetworkEntry = () => { networkEntry.value.networkId = ''; networkEntry.value.rpcUrl = ''; networkEntry.value.customNetworkId = ''; networkEntry.value.customChainId = null; }; // Функция получения списка всех доступных сетей в плоском формате const getAllNetworks = () => { return networks.value; }; // Функция получения метаданных сети по ID const getNetworkMetadata = (networkId) => { return networks.value.find(network => network.value === networkId) || null; }; // Состояние для тестирования RPC const testingRpc = ref(false); const testingRpcId = ref(''); // Функция для тестирования RPC-соединения const testRpcConnection = async (networkId, rpcUrl) => { testingRpc.value = true; testingRpcId.value = networkId; try { // Формируем запрос на бэкенд для проверки RPC const response = await axios.post('/api/settings/rpc-test', { networkId, rpcUrl }); if (response.data && response.data.success) { return { success: true, message: `Соединение с ${networkId} успешно установлено! Номер блока: ${response.data.blockNumber}`, blockNumber: response.data.blockNumber }; } else { return { success: false, error: response.data?.error || 'Не удалось установить соединение' }; } } catch (error) { console.error('[useBlockchainNetworks] Ошибка при тестировании RPC:', error); return { success: false, error: error.response?.data?.error || error.message || 'Неизвестная ошибка' }; } finally { testingRpc.value = false; testingRpcId.value = ''; } }; return { // Данные networkGroups, networkEntry, testingRpc, testingRpcId, networks, // Экспортируем плоский список сетей // Методы getChainIdByNetworkId, validateAndPrepareNetworkConfig, resetNetworkEntry, getAllNetworks, getNetworkMetadata, testRpcConnection }; }