rwadurian/backend/mpc-system/services/service-party-app/electron/preload.ts

200 lines
7.0 KiB
TypeScript

import { contextBridge, ipcRenderer } from 'electron';
// 事件订阅管理
const eventSubscriptions: Map<string, (event: unknown, ...args: unknown[]) => void> = new Map();
// 暴露给渲染进程的 API
contextBridge.exposeInMainWorld('electronAPI', {
// ===========================================================================
// gRPC 相关 - Keygen
// ===========================================================================
grpc: {
createSession: (params: {
walletName: string;
thresholdT: number;
thresholdN: number;
initiatorName: string;
}) => ipcRenderer.invoke('grpc:createSession', params),
joinSession: (sessionId: string, participantName: string) =>
ipcRenderer.invoke('grpc:joinSession', { sessionId, participantName }),
validateInviteCode: (code: string) =>
ipcRenderer.invoke('grpc:validateInviteCode', { code }),
getSessionStatus: (sessionId: string) =>
ipcRenderer.invoke('grpc:getSessionStatus', { sessionId }),
subscribeSessionEvents: (sessionId: string, callback: (event: unknown) => void) => {
const channel = `session:events:${sessionId}`;
const listener = (_event: unknown, data: unknown) => callback(data);
eventSubscriptions.set(channel, listener);
ipcRenderer.on(channel, listener);
ipcRenderer.send('grpc:subscribeSessionEvents', { sessionId });
return () => {
ipcRenderer.removeListener(channel, listener);
eventSubscriptions.delete(channel);
ipcRenderer.send('grpc:unsubscribeSessionEvents', { sessionId });
};
},
testConnection: (url: string) =>
ipcRenderer.invoke('grpc:testConnection', { url }),
// 签名相关
validateSigningSession: (code: string) =>
ipcRenderer.invoke('grpc:validateSigningSession', { code }),
joinSigningSession: (params: {
sessionId: string;
shareId: string;
password: string;
}) => ipcRenderer.invoke('grpc:joinSigningSession', params),
subscribeSigningProgress: (sessionId: string, callback: (event: unknown) => void) => {
const channel = `signing:progress:${sessionId}`;
const listener = (_event: unknown, data: unknown) => callback(data);
eventSubscriptions.set(channel, listener);
ipcRenderer.on(channel, listener);
ipcRenderer.send('grpc:subscribeSigningProgress', { sessionId });
return () => {
ipcRenderer.removeListener(channel, listener);
eventSubscriptions.delete(channel);
ipcRenderer.send('grpc:unsubscribeSigningProgress', { sessionId });
};
},
},
// ===========================================================================
// 存储相关 (SQLite)
// ===========================================================================
storage: {
// Share 操作
saveShare: (share: {
sessionId: string;
walletName: string;
partyId: string;
partyIndex: number;
threshold: { t: number; n: number };
publicKey: string;
rawShare: string;
participants?: Array<{ partyId: string; name: string }>;
}, password: string) =>
ipcRenderer.invoke('storage:saveShare', { share, password }),
listShares: () => ipcRenderer.invoke('storage:listShares'),
getShare: (id: string, password: string) =>
ipcRenderer.invoke('storage:getShare', { id, password }),
exportShare: (id: string, password: string) =>
ipcRenderer.invoke('storage:exportShare', { id, password }),
importShare: (filePath: string, password: string) =>
ipcRenderer.invoke('storage:importShare', { filePath, password }),
deleteShare: (id: string) =>
ipcRenderer.invoke('storage:deleteShare', { id }),
// 设置操作
getSettings: () => ipcRenderer.invoke('storage:getSettings'),
saveSettings: (settings: {
messageRouterUrl?: string;
autoBackup?: boolean;
backupPath?: string;
}) => ipcRenderer.invoke('storage:saveSettings', { settings }),
},
// ===========================================================================
// 地址派生相关
// ===========================================================================
address: {
// 派生指定链的地址
derive: (shareId: string, chain: string, password: string) =>
ipcRenderer.invoke('address:derive', { shareId, chain, password }),
// 派生所有支持链的地址
deriveAll: (shareId: string, password: string) =>
ipcRenderer.invoke('address:deriveAll', { shareId, password }),
// 获取 share 的所有派生地址
list: (shareId: string) =>
ipcRenderer.invoke('address:list', { shareId }),
// 获取支持的链列表
getSupportedChains: () =>
ipcRenderer.invoke('address:getSupportedChains'),
},
// ===========================================================================
// 签名历史相关
// ===========================================================================
signing: {
// 获取签名历史
getHistory: (shareId: string) =>
ipcRenderer.invoke('signing:getHistory', { shareId }),
},
// ===========================================================================
// Kava 区块链相关
// ===========================================================================
kava: {
// 查询 KAVA 余额
getBalance: (address: string) =>
ipcRenderer.invoke('kava:getBalance', { address }),
// 查询所有余额
getAllBalances: (address: string) =>
ipcRenderer.invoke('kava:getAllBalances', { address }),
// 查询账户信息
getAccountInfo: (address: string) =>
ipcRenderer.invoke('kava:getAccountInfo', { address }),
// 构建转账交易 (待 TSS 签名)
buildSendTx: (params: {
fromAddress: string;
toAddress: string;
amount: string;
publicKeyHex: string;
memo?: string;
}) => ipcRenderer.invoke('kava:buildSendTx', params),
// 完成签名并广播交易
completeTxAndBroadcast: (params: {
unsignedTx: unknown;
signatureHex: string;
}) => ipcRenderer.invoke('kava:completeTxAndBroadcast', params),
// 查询交易状态
getTxStatus: (txHash: string) =>
ipcRenderer.invoke('kava:getTxStatus', { txHash }),
// 获取配置
getConfig: () => ipcRenderer.invoke('kava:getConfig'),
// 更新配置
updateConfig: (config: {
lcdEndpoint?: string;
rpcEndpoint?: string;
chainId?: string;
}) => ipcRenderer.invoke('kava:updateConfig', { config }),
},
// ===========================================================================
// 对话框相关
// ===========================================================================
dialog: {
selectDirectory: () => ipcRenderer.invoke('dialog:selectDirectory'),
selectFile: (filters?: { name: string; extensions: string[] }[]) =>
ipcRenderer.invoke('dialog:selectFile', { filters }),
saveFile: (defaultPath?: string, filters?: { name: string; extensions: string[] }[]) =>
ipcRenderer.invoke('dialog:saveFile', { defaultPath, filters }),
},
});