diff --git a/backend/mpc-system/services/service-party-app/electron/main.ts b/backend/mpc-system/services/service-party-app/electron/main.ts index 73cd08f9..19adb1d3 100644 --- a/backend/mpc-system/services/service-party-app/electron/main.ts +++ b/backend/mpc-system/services/service-party-app/electron/main.ts @@ -1,6 +1,7 @@ import { app, BrowserWindow, ipcMain, shell, dialog } from 'electron'; import * as path from 'path'; import * as fs from 'fs'; +import * as crypto from 'crypto'; import express from 'express'; import { GrpcClient } from './modules/grpc-client'; import { DatabaseManager } from './modules/database'; @@ -83,14 +84,27 @@ function startHttpServer() { }); } +// 生成或获取持久化的 partyId +function getOrCreatePartyId(db: DatabaseManager): string { + const settings = db.getAllSettings(); + let partyId = settings['party_id']; + if (!partyId) { + // 生成一个新的 UUID 作为 partyId + partyId = crypto.randomUUID(); + db.setSetting('party_id', partyId); + console.log('Generated new partyId:', partyId); + } + return partyId; +} + // 初始化服务 async function initServices() { + // 初始化数据库 (必须首先初始化) + database = new DatabaseManager(); + // 初始化 gRPC 客户端 grpcClient = new GrpcClient(); - // 初始化数据库 - database = new DatabaseManager(); - // 初始化 Kava 交易服务 kavaTxService = new KavaTxService(KAVA_MAINNET_TX_CONFIG); @@ -102,6 +116,39 @@ async function initServices() { // 设置 IPC 处理器 setupIpcHandlers(); + + // 启动时自动连接并注册到 Message Router + await connectAndRegisterToMessageRouter(); +} + +// 连接并注册到 Message Router +async function connectAndRegisterToMessageRouter() { + if (!grpcClient || !database) { + console.error('gRPC client or database not initialized'); + return; + } + + try { + const settings = database.getAllSettings(); + const routerUrl = settings['message_router_url'] || 'mpc-grpc.szaiai.com:443'; + const partyId = getOrCreatePartyId(database); + const role = 'temporary'; // Service-Party-App 使用 temporary 角色 + + console.log(`Connecting to Message Router: ${routerUrl}...`); + await grpcClient.connect(routerUrl); + console.log('Connected to Message Router'); + + console.log(`Registering as party: ${partyId} (role: ${role})...`); + await grpcClient.registerParty(partyId, role); + console.log('Registered to Message Router successfully'); + + // 订阅会话事件 + grpcClient.subscribeSessionEvents(partyId); + console.log('Subscribed to session events'); + } catch (error) { + console.error('Failed to connect/register to Message Router:', (error as Error).message); + // 不抛出错误,允许应用继续启动,用户可以稍后手动重试 + } } // 设置 IPC 通信处理器 @@ -111,9 +158,9 @@ function setupIpcHandlers() { // =========================================================================== // gRPC 连接 - ipcMain.handle('grpc:connect', async (_event, { host, port }) => { + ipcMain.handle('grpc:connect', async (_event, { url }) => { try { - await grpcClient?.connect(host, port); + await grpcClient?.connect(url); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; @@ -227,6 +274,26 @@ function setupIpcHandlers() { } }); + // gRPC - 获取当前 partyId + ipcMain.handle('grpc:getPartyId', async () => { + try { + const partyId = grpcClient?.getPartyId(); + return { success: true, partyId: partyId || null }; + } catch (error) { + return { success: false, error: (error as Error).message, partyId: null }; + } + }); + + // gRPC - 检查连接状态 + ipcMain.handle('grpc:isConnected', async () => { + try { + const connected = grpcClient?.isConnected() || false; + return { success: true, connected }; + } catch (error) { + return { success: false, error: (error as Error).message, connected: false }; + } + }); + // gRPC - 验证签名会话 (通过 Account 服务 HTTP API) ipcMain.handle('grpc:validateSigningSession', async (_event, { code }) => { try { diff --git a/backend/mpc-system/services/service-party-app/electron/preload.ts b/backend/mpc-system/services/service-party-app/electron/preload.ts index 2a903fb7..ea9d24bd 100644 --- a/backend/mpc-system/services/service-party-app/electron/preload.ts +++ b/backend/mpc-system/services/service-party-app/electron/preload.ts @@ -46,6 +46,19 @@ contextBridge.exposeInMainWorld('electronAPI', { getRegisteredParties: (roleFilter?: string, onlyOnline?: boolean) => ipcRenderer.invoke('grpc:getRegisteredParties', { roleFilter, onlyOnline }), + // 获取当前 partyId + getPartyId: () => ipcRenderer.invoke('grpc:getPartyId'), + + // 检查连接状态 + isConnected: () => ipcRenderer.invoke('grpc:isConnected'), + + // 连接到 Message Router + connect: (url: string) => ipcRenderer.invoke('grpc:connect', { url }), + + // 注册为参与方 + register: (partyId: string, role: string) => + ipcRenderer.invoke('grpc:register', { partyId, role }), + // 签名相关 validateSigningSession: (code: string) => ipcRenderer.invoke('grpc:validateSigningSession', { code }), diff --git a/backend/mpc-system/services/service-party-app/src/stores/appStore.ts b/backend/mpc-system/services/service-party-app/src/stores/appStore.ts index dc4dfab7..22172eec 100644 --- a/backend/mpc-system/services/service-party-app/src/stores/appStore.ts +++ b/backend/mpc-system/services/service-party-app/src/stores/appStore.ts @@ -101,25 +101,61 @@ export const useAppStore = create((set, get) => ({ checkAllServices: async () => { const { setMessageRouterStatus, setKavaApiStatus, setDatabaseStatus, setAppReady } = get(); - // 检测 Message Router + // 检测 Message Router - 真实验证注册状态 setMessageRouterStatus({ status: 'checking', message: '正在检测...' }); try { if (window.electronAPI) { const settings = await window.electronAPI.storage.getSettings(); const routerUrl = settings?.messageRouterUrl || 'mpc-grpc.szaiai.com:443'; - const result = await window.electronAPI.grpc.testConnection(routerUrl); - if (result.success) { + + // 1. 检查是否已连接 + const connResult = await window.electronAPI.grpc.isConnected(); + if (!connResult.connected) { setMessageRouterStatus({ - status: 'connected', - message: routerUrl, + status: 'disconnected', + message: '未连接到 ' + routerUrl, lastChecked: new Date(), }); } else { - setMessageRouterStatus({ - status: 'error', - message: result.error || '连接失败', - lastChecked: new Date(), - }); + // 2. 已连接,检查是否已注册 + const partyIdResult = await window.electronAPI.grpc.getPartyId(); + if (!partyIdResult.partyId) { + setMessageRouterStatus({ + status: 'disconnected', + message: '已连接但未注册', + lastChecked: new Date(), + }); + } else { + // 3. 已注册,从 Message Router 验证自己是否在注册列表中 + const partiesResult = await window.electronAPI.grpc.getRegisteredParties(); + if (partiesResult.success) { + const selfRegistered = partiesResult.parties.some( + (p) => p.partyId === partyIdResult.partyId + ); + if (selfRegistered) { + const selfParty = partiesResult.parties.find( + (p) => p.partyId === partyIdResult.partyId + ); + setMessageRouterStatus({ + status: 'connected', + message: `已注册 (${selfParty?.online ? '在线' : '离线'})`, + lastChecked: new Date(), + }); + } else { + setMessageRouterStatus({ + status: 'error', + message: '注册验证失败', + lastChecked: new Date(), + }); + } + } else { + setMessageRouterStatus({ + status: 'error', + message: partiesResult.error || '获取注册列表失败', + lastChecked: new Date(), + }); + } + } } } else { setMessageRouterStatus({ diff --git a/backend/mpc-system/services/service-party-app/src/types/electron.d.ts b/backend/mpc-system/services/service-party-app/src/types/electron.d.ts index 11d1ce9e..87d867f5 100644 --- a/backend/mpc-system/services/service-party-app/src/types/electron.d.ts +++ b/backend/mpc-system/services/service-party-app/src/types/electron.d.ts @@ -430,6 +430,14 @@ interface ElectronAPI { testConnection: (url: string) => Promise; // 获取已注册的参与方列表 getRegisteredParties: (roleFilter?: string, onlyOnline?: boolean) => Promise; + // 获取当前 partyId + getPartyId: () => Promise<{ success: boolean; partyId: string | null; error?: string }>; + // 检查连接状态 + isConnected: () => Promise<{ success: boolean; connected: boolean; error?: string }>; + // 连接到 Message Router + connect: (url: string) => Promise<{ success: boolean; error?: string }>; + // 注册为参与方 + register: (partyId: string, role: string) => Promise<{ success: boolean; error?: string }>; // 签名相关 validateSigningSession: (code: string) => Promise; joinSigningSession: (params: JoinSigningSessionParams) => Promise;