ваше сообщение коммита

This commit is contained in:
2025-07-27 03:30:13 +03:00
parent 057fe6254c
commit 1835632be9
141 changed files with 32514 additions and 6661 deletions

View File

@@ -0,0 +1,85 @@
/**
* 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/HB3-ACCELERATOR
*/
import axios from 'axios';
/**
* Сервис для работы с DLE v2 (Digital Legal Entity)
* Современный подход с единым контрактом
*/
class DLEV2Service {
/**
* Создает новое DLE v2
* @param {Object} dleParams - Параметры DLE
* @returns {Promise<Object>} - Результат создания
*/
async createDLE(dleParams) {
try {
const response = await axios.post('/api/dle-v2', dleParams);
return response.data;
} catch (error) {
console.error('Ошибка при создании DLE v2:', error);
throw error;
}
}
/**
* Получает список всех DLE v2
* @returns {Promise<Array>} - Список DLE v2
*/
async getAllDLEs() {
try {
const response = await axios.get('/api/dle-v2');
return response.data.data || [];
} catch (error) {
console.error('Ошибка при получении списка DLE v2:', error);
return [];
}
}
/**
* Получает настройки по умолчанию для DLE v2
* @returns {Promise<Object>} - Настройки по умолчанию
*/
async getDefaults() {
try {
const response = await axios.get('/api/dle-v2/defaults');
return response.data.data;
} catch (error) {
console.error('Ошибка при получении настроек по умолчанию DLE v2:', error);
return {
votingDelay: 1,
votingPeriod: 45818,
proposalThreshold: '100000',
quorumPercentage: 4,
minTimelockDelay: 2
};
}
}
/**
* Удаляет DLE v2 по адресу
* @param {string} dleAddress - Адрес DLE
* @returns {Promise<Object>} - Результат удаления
*/
async deleteDLE(dleAddress) {
try {
const response = await axios.delete(`/api/dle-v2/${dleAddress}`);
return response.data;
} catch (error) {
console.error('Ошибка при удалении DLE v2:', error);
throw error;
}
}
}
export default new DLEV2Service();

View File

@@ -49,6 +49,7 @@ export async function connectWithWallet() {
const origin = window.location.origin;
const statement = 'Sign in with Ethereum to the app.';
const issuedAt = new Date().toISOString();
const siweMessage = new SiweMessage({
domain,
address,
@@ -57,11 +58,23 @@ export async function connectWithWallet() {
version: '1',
chainId: 1,
nonce,
issuedAt,
resources: [`${origin}/api/auth/verify`],
});
const message = siweMessage.prepareMessage();
console.log('SIWE message:', message);
console.log('SIWE message details:', {
domain,
address,
statement,
uri: origin,
version: '1',
chainId: 1,
nonce,
issuedAt,
resources: [`${origin}/api/auth/verify`],
});
// Запрашиваем подпись
console.log('Requesting signature...');
@@ -75,9 +88,10 @@ export async function connectWithWallet() {
// Отправляем подпись на сервер для верификации
console.log('Sending verification request...');
const verificationResponse = await axios.post('/auth/verify', {
message,
signature,
address,
nonce,
issuedAt,
});
console.log('Verification response:', verificationResponse.data);

View File

@@ -0,0 +1,192 @@
/**
* WebSocket сервис для реального времени обновлений
*/
class WebSocketService {
constructor() {
this.ws = null;
this.isConnected = false;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectDelay = 1000; // 1 секунда
this.listeners = new Map();
this.userId = null;
}
// Подключение к WebSocket серверу
connect(userId = null) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
console.log('🔌 [WebSocket] Уже подключен');
return;
}
this.userId = userId;
try {
// Определяем WebSocket URL
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
// В Docker окружении backend работает на порту 8000
const backendHost = window.location.hostname + ':8000';
const wsUrl = `${protocol}//${backendHost}/ws`;
console.log('🔌 [WebSocket] Подключение к:', wsUrl);
this.ws = new WebSocket(wsUrl);
this.ws.onopen = () => {
console.log('✅ [WebSocket] Подключение установлено');
this.isConnected = true;
this.reconnectAttempts = 0;
// Аутентификация пользователя
if (this.userId) {
this.send({
type: 'auth',
userId: this.userId
});
}
this.emit('connected');
};
this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('📨 [WebSocket] Получено сообщение:', data);
this.handleMessage(data);
} catch (error) {
console.error('❌ [WebSocket] Ошибка парсинга сообщения:', error);
}
};
this.ws.onclose = (event) => {
console.log('🔌 [WebSocket] Соединение закрыто:', event.code, event.reason);
this.isConnected = false;
this.emit('disconnected', event);
// Попытка переподключения
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`🔄 [WebSocket] Попытка переподключения ${this.reconnectAttempts}/${this.maxReconnectAttempts}`);
setTimeout(() => {
this.connect(this.userId);
}, this.reconnectDelay * this.reconnectAttempts);
} else {
console.error('❌ [WebSocket] Превышено максимальное количество попыток переподключения');
this.emit('reconnect-failed');
}
};
this.ws.onerror = (error) => {
console.error('❌ [WebSocket] Ошибка соединения:', error);
this.emit('error', error);
};
} catch (error) {
console.error('❌ [WebSocket] Ошибка создания соединения:', error);
this.emit('error', error);
}
}
// Отправка сообщения
send(data) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
} else {
console.warn('⚠️ [WebSocket] Соединение не установлено, сообщение не отправлено:', data);
}
}
// Обработка входящих сообщений
handleMessage(data) {
switch (data.type) {
case 'auth-success':
console.log('✅ [WebSocket] Аутентификация успешна для пользователя:', data.userId);
this.emit('auth-success', data);
break;
case 'chat-message':
console.log('💬 [WebSocket] Новое сообщение чата:', data.message);
this.emit('chat-message', data.message);
break;
case 'conversation-updated':
console.log('📝 [WebSocket] Обновление диалога:', data.conversationId);
this.emit('conversation-updated', data.conversationId);
break;
case 'messages-updated':
console.log('📨 [WebSocket] Обновление сообщений');
this.emit('messages-updated');
break;
case 'contacts-updated':
console.log('👥 [WebSocket] Обновление контактов');
this.emit('contacts-updated');
break;
default:
console.log('❓ [WebSocket] Неизвестный тип сообщения:', data.type);
this.emit('unknown-message', data);
}
}
// Подписка на события
on(event, callback) {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event).push(callback);
}
// Отписка от событий
off(event, callback) {
if (this.listeners.has(event)) {
const callbacks = this.listeners.get(event);
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
}
// Эмиссия событий
emit(event, data) {
if (this.listeners.has(event)) {
this.listeners.get(event).forEach(callback => {
try {
callback(data);
} catch (error) {
console.error(`❌ [WebSocket] Ошибка в обработчике события ${event}:`, error);
}
});
}
}
// Отключение
disconnect() {
if (this.ws) {
this.ws.close();
this.ws = null;
}
this.isConnected = false;
this.listeners.clear();
console.log('🔌 [WebSocket] Отключен');
}
// Получение статуса соединения
getStatus() {
return {
isConnected: this.isConnected,
readyState: this.ws ? this.ws.readyState : null,
reconnectAttempts: this.reconnectAttempts,
userId: this.userId
};
}
}
// Создаем единственный экземпляр
const websocketService = new WebSocketService();
export default websocketService;