rwadurian/backend/mpc-system/services/service-party-app/src/stores/appStore.ts

299 lines
8.9 KiB
TypeScript

import { create } from 'zustand';
// =============================================================================
// 类型定义
// =============================================================================
export type ConnectionStatus = 'unknown' | 'checking' | 'connected' | 'disconnected' | 'error';
export type AppReadyState = 'initializing' | 'ready' | 'error';
export type OperationStatus = 'idle' | 'connecting' | 'in_progress' | 'completed' | 'failed';
export interface ServiceStatus {
status: ConnectionStatus;
message?: string;
lastChecked?: Date;
}
export interface OperationProgress {
status: OperationStatus;
type?: 'keygen' | 'sign';
sessionId?: string;
currentStep?: number;
totalSteps?: number;
stepDescription?: string;
error?: string;
}
export interface EnvironmentCheck {
messageRouter: ServiceStatus;
kavaApi: ServiceStatus;
database: ServiceStatus;
}
interface AppState {
// 应用就绪状态
appReady: AppReadyState;
appError?: string;
// 环境检测结果
environment: EnvironmentCheck;
// 当前操作进度
operation: OperationProgress;
// Actions
setAppReady: (state: AppReadyState, error?: string) => void;
setMessageRouterStatus: (status: ServiceStatus) => void;
setKavaApiStatus: (status: ServiceStatus) => void;
setDatabaseStatus: (status: ServiceStatus) => void;
setOperation: (operation: Partial<OperationProgress>) => void;
resetOperation: () => void;
checkAllServices: () => Promise<void>;
}
// =============================================================================
// Store
// =============================================================================
export const useAppStore = create<AppState>((set, get) => ({
// 初始状态
appReady: 'initializing',
appError: undefined,
environment: {
messageRouter: { status: 'unknown' },
kavaApi: { status: 'unknown' },
database: { status: 'unknown' },
},
operation: {
status: 'idle',
},
// Actions
setAppReady: (state, error) => set({ appReady: state, appError: error }),
setMessageRouterStatus: (status) =>
set((s) => ({
environment: { ...s.environment, messageRouter: status },
})),
setKavaApiStatus: (status) =>
set((s) => ({
environment: { ...s.environment, kavaApi: status },
})),
setDatabaseStatus: (status) =>
set((s) => ({
environment: { ...s.environment, database: status },
})),
setOperation: (operation) =>
set((s) => ({
operation: { ...s.operation, ...operation },
})),
resetOperation: () =>
set({
operation: { status: 'idle' },
}),
checkAllServices: async () => {
const { setMessageRouterStatus, setKavaApiStatus, setDatabaseStatus, setAppReady } = get();
// 检测 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';
// 1. 检查是否已连接
const connResult = await window.electronAPI.grpc.isConnected();
if (!connResult.connected) {
setMessageRouterStatus({
status: 'disconnected',
message: '未连接到 ' + routerUrl,
lastChecked: new Date(),
});
} else {
// 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({
status: 'disconnected',
message: '非 Electron 环境',
});
}
} catch (error) {
setMessageRouterStatus({
status: 'error',
message: (error as Error).message,
lastChecked: new Date(),
});
}
// 检测 Kava API
setKavaApiStatus({ status: 'checking', message: '正在检测...' });
try {
if (window.electronAPI) {
// 使用健康检查 API (查询最新区块)
const result = await window.electronAPI.kava.healthCheck();
if (result.success && result.data?.ok) {
const config = await window.electronAPI.kava.getConfig();
const latencyMsg = result.data.latency ? ` (${result.data.latency}ms)` : '';
setKavaApiStatus({
status: 'connected',
message: (config?.lcdEndpoint || 'Kava Mainnet') + latencyMsg,
lastChecked: new Date(),
});
} else {
setKavaApiStatus({
status: 'error',
message: result.data?.error || result.error || 'API 响应异常',
lastChecked: new Date(),
});
}
} else {
setKavaApiStatus({
status: 'disconnected',
message: '非 Electron 环境',
});
}
} catch (error) {
setKavaApiStatus({
status: 'error',
message: (error as Error).message,
lastChecked: new Date(),
});
}
// 检测数据库
setDatabaseStatus({ status: 'checking', message: '正在检测...' });
try {
if (window.electronAPI) {
const result = await window.electronAPI.storage.listShares();
if (result.success) {
setDatabaseStatus({
status: 'connected',
message: `${result.data?.length || 0} 个钱包`,
lastChecked: new Date(),
});
} else {
setDatabaseStatus({
status: 'error',
message: result.error || '数据库错误',
lastChecked: new Date(),
});
}
} else {
setDatabaseStatus({
status: 'disconnected',
message: '非 Electron 环境',
});
}
} catch (error) {
setDatabaseStatus({
status: 'error',
message: (error as Error).message,
lastChecked: new Date(),
});
}
// 判断整体就绪状态
const env = get().environment;
const hasError =
env.messageRouter.status === 'error' ||
env.kavaApi.status === 'error' ||
env.database.status === 'error';
if (hasError) {
setAppReady('error', '部分服务连接失败,请检查设置');
} else {
setAppReady('ready');
}
},
}));
// =============================================================================
// 辅助函数
// =============================================================================
export function getOverallStatus(env: EnvironmentCheck): ConnectionStatus {
const statuses = [env.messageRouter.status, env.kavaApi.status, env.database.status];
if (statuses.includes('checking')) return 'checking';
if (statuses.includes('error')) return 'error';
if (statuses.every((s) => s === 'connected')) return 'connected';
if (statuses.includes('disconnected')) return 'disconnected';
return 'unknown';
}
export function getStatusColor(status: ConnectionStatus): string {
switch (status) {
case 'connected':
return '#22c55e'; // green
case 'checking':
return '#f59e0b'; // yellow
case 'disconnected':
return '#6b7280'; // gray
case 'error':
return '#ef4444'; // red
default:
return '#6b7280'; // gray
}
}
export function getStatusText(status: ConnectionStatus): string {
switch (status) {
case 'connected':
return '已连接';
case 'checking':
return '检测中...';
case 'disconnected':
return '未连接';
case 'error':
return '连接失败';
default:
return '未知';
}
}