Files
DLE/frontend/src/views/settings/RpcProvidersSettings.vue
2025-10-30 22:41:04 +03:00

150 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
Copyright (c) 2024-2025 Тарабанов Александр Викторович
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
-->
<template>
<div class="rpc-providers-settings">
<h4>RPC Провайдеры</h4>
<div v-if="Array.isArray(rpcConfigs) && rpcConfigs.length > 0" class="rpc-list">
<div v-for="(rpc, index) in rpcConfigs" :key="rpc.networkId" class="rpc-entry">
<span><strong>ID Сети:</strong> {{ rpc.networkId }}</span>
<span><strong>URL:</strong> {{ rpc.rpcUrlDisplay || rpc.rpcUrl }}</span>
<span v-if="rpc.chainId"><strong>Chain ID:</strong> {{ rpc.chainId }}</span>
<button class="btn btn-info btn-sm" @click="testRpc(rpc)" :disabled="testingRpc && testingRpcId === rpc.networkId">
<i class="fas" :class="testingRpc && testingRpcId === rpc.networkId ? 'fa-spinner fa-spin' : 'fa-check-circle'"></i>
{{ testingRpc && testingRpcId === rpc.networkId ? 'Проверка...' : 'Тест' }}
</button>
<button class="btn btn-danger btn-sm" @click="removeRpc(index)">Удалить</button>
</div>
</div>
<p v-else>Нет добавленных RPC конфигураций.</p>
<div class="add-rpc-form">
<h5>Добавить новую RPC конфигурацию:</h5>
<div class="form-group">
<label>ID Сети:</label>
<select v-model="networkEntry.networkId" class="form-control">
<optgroup v-for="(group, groupIndex) in networkGroups" :key="groupIndex" :label="group.label">
<option v-for="option in group.options" :key="option.value" :value="option.value">
{{ option.label }}
</option>
</optgroup>
</select>
<div v-if="networkEntry.networkId === 'custom'" class="mt-2">
<label>Пользовательский ID:</label>
<input type="text" v-model="networkEntry.customNetworkId" class="form-control" placeholder="Введите ID сети">
<label class="mt-2">Chain ID:</label>
<input type="number" v-model.number="networkEntry.customChainId" class="form-control" placeholder="Например, 1 для Ethereum">
<small>Chain ID - уникальный идентификатор блокчейн-сети (целое число)</small>
</div>
</div>
<div class="form-group">
<label>RPC URL:</label>
<input type="text" v-model="networkEntry.rpcUrl" class="form-control" placeholder="https://...">
</div>
<button class="btn btn-secondary" @click="addRpc">Добавить RPC</button>
</div>
</div>
</template>
<script setup>
import { ref, toRefs } from 'vue';
import useBlockchainNetworks from '@/composables/useBlockchainNetworks';
import api from '@/api/axios';
const props = defineProps({
rpcConfigs: { type: Array, required: true, default: () => [] }
});
const emit = defineEmits(['update', 'test']);
const {
networkGroups,
networkEntry,
validateAndPrepareNetworkConfig,
resetNetworkEntry,
testRpcConnection,
testingRpc,
testingRpcId
} = useBlockchainNetworks();
async function addRpc() {
const result = validateAndPrepareNetworkConfig();
if (!result.valid) {
alert(result.error);
return;
}
const { networkId, rpcUrl, chainId } = result.networkConfig;
if (props.rpcConfigs.some(rpc => rpc.networkId === networkId)) {
alert(`Ошибка: RPC конфигурация для сети с ID '${networkId}' уже существует.`);
return;
}
try {
await api.post('/settings/rpc', { networkId, rpcUrl, chainId });
emit('update'); // сигнал родителю перезагрузить список
resetNetworkEntry();
} catch (e) {
alert('Ошибка при добавлении RPC: ' + (e.response?.data?.error || e.message));
}
}
async function removeRpc(index) {
const rpc = props.rpcConfigs[index];
if (!rpc) return;
if (!confirm(`Удалить RPC для сети ${rpc.networkId}?`)) return;
try {
await api.delete(`/settings/rpc/${rpc.networkId}`);
emit('update');
} catch (e) {
alert('Ошибка при удалении RPC: ' + (e.response?.data?.error || e.message));
}
}
async function testRpc(rpc) {
if (!rpc.networkId || !rpc.rpcUrl) {
alert('Для теста RPC нужно указать и ID сети, и URL');
return;
}
const result = await testRpcConnection(rpc.networkId, rpc.rpcUrl);
if (result.success) {
alert(result.message);
} else {
alert(`Ошибка при подключении к ${rpc.networkId}: ${result.error}`);
}
}
</script>
<style scoped>
.rpc-list { margin-bottom: 1rem; }
.rpc-entry { display: flex; gap: 1rem; align-items: center; margin-bottom: 0.5rem; }
.add-rpc-form { margin-top: 1rem; }
.suggestion {
background-color: rgba(76, 175, 80, 0.1);
border-left: 3px solid var(--color-primary, #4caf50);
padding: 6px 10px;
margin-top: 8px;
border-radius: 0 4px 4px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.btn-link {
background: none;
border: none;
padding: 0;
color: var(--color-primary, #4caf50);
text-decoration: underline;
cursor: pointer;
font-size: 0.875rem;
}
.btn-link:hover {
color: var(--color-primary-dark, #388e3c);
text-decoration: none;
}
.mt-2 { margin-top: 10px; }
</style>