330 lines
11 KiB
TypeScript
330 lines
11 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: (params: {
|
|
sessionId: string;
|
|
partyId: string;
|
|
joinToken: string;
|
|
walletName?: string;
|
|
}) => ipcRenderer.invoke('grpc:joinSession', params),
|
|
|
|
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 }),
|
|
|
|
// 获取已注册的参与方列表
|
|
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 }),
|
|
|
|
// 签名相关 (旧版 - persistent 签名使用)
|
|
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 });
|
|
};
|
|
},
|
|
},
|
|
|
|
// ===========================================================================
|
|
// Co-Sign 相关 - 全新的多方协作签名 API
|
|
// ===========================================================================
|
|
cosign: {
|
|
// 创建 Co-Sign 会话
|
|
createSession: (params: {
|
|
shareId: string;
|
|
sharePassword: string;
|
|
messageHash: string;
|
|
initiatorName?: string;
|
|
}) => ipcRenderer.invoke('cosign:createSession', params),
|
|
|
|
// 验证邀请码
|
|
validateInviteCode: (code: string) =>
|
|
ipcRenderer.invoke('cosign:validateInviteCode', { code }),
|
|
|
|
// 加入 Co-Sign 会话
|
|
joinSession: (params: {
|
|
sessionId: string;
|
|
shareId: string;
|
|
sharePassword: string;
|
|
joinToken: string;
|
|
walletName?: string;
|
|
messageHash: string;
|
|
threshold: { t: number; n: number };
|
|
}) => ipcRenderer.invoke('cosign:joinSession', params),
|
|
|
|
// 获取会话状态
|
|
getSessionStatus: (sessionId: string) =>
|
|
ipcRenderer.invoke('cosign:getSessionStatus', { sessionId }),
|
|
|
|
// 订阅会话事件
|
|
subscribeSessionEvents: (sessionId: string, callback: (event: unknown) => void) => {
|
|
const channel = `cosign:events:${sessionId}`;
|
|
const listener = (_event: unknown, data: unknown) => callback(data);
|
|
eventSubscriptions.set(channel, listener);
|
|
ipcRenderer.on(channel, listener);
|
|
ipcRenderer.send('cosign:subscribeSessionEvents', { sessionId });
|
|
|
|
return () => {
|
|
ipcRenderer.removeListener(channel, listener);
|
|
eventSubscriptions.delete(channel);
|
|
ipcRenderer.send('cosign:unsubscribeSessionEvents', { sessionId });
|
|
};
|
|
},
|
|
},
|
|
|
|
// ===========================================================================
|
|
// Account 服务相关 (HTTP API)
|
|
// ===========================================================================
|
|
account: {
|
|
// 创建签名会话
|
|
createSignSession: (params: {
|
|
shareId: string;
|
|
password: string;
|
|
messageHash: string;
|
|
initiatorName?: string;
|
|
}) => ipcRenderer.invoke('account:createSignSession', params),
|
|
|
|
// 获取签名会话状态 (通过邀请码)
|
|
getSignSessionByInviteCode: (inviteCode: string) =>
|
|
ipcRenderer.invoke('account:getSignSessionByInviteCode', { inviteCode }),
|
|
|
|
// 健康检查
|
|
healthCheck: () => ipcRenderer.invoke('account:healthCheck'),
|
|
|
|
// 测试连接
|
|
testConnection: () => ipcRenderer.invoke('account:testConnection'),
|
|
|
|
// 更新服务 URL
|
|
updateUrl: (url: string) =>
|
|
ipcRenderer.invoke('account:updateUrl', { url }),
|
|
|
|
// 获取当前服务 URL
|
|
getUrl: () => ipcRenderer.invoke('account:getUrl'),
|
|
},
|
|
|
|
// ===========================================================================
|
|
// 存储相关 (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 }),
|
|
|
|
// 健康检查
|
|
healthCheck: () => ipcRenderer.invoke('kava:healthCheck'),
|
|
|
|
// 切换网络 (mainnet/testnet)
|
|
switchNetwork: (network: 'mainnet' | 'testnet') =>
|
|
ipcRenderer.invoke('kava:switchNetwork', { network }),
|
|
|
|
// 获取当前网络
|
|
getNetwork: () => ipcRenderer.invoke('kava:getNetwork'),
|
|
},
|
|
|
|
// ===========================================================================
|
|
// 对话框相关
|
|
// ===========================================================================
|
|
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 }),
|
|
},
|
|
|
|
// ===========================================================================
|
|
// 调试相关
|
|
// ===========================================================================
|
|
debug: {
|
|
// 订阅主进程日志
|
|
subscribeLogs: (callback: (event: unknown, data: { level: string; source: string; message: string }) => void) => {
|
|
ipcRenderer.on('debug:log', callback);
|
|
ipcRenderer.send('debug:subscribe');
|
|
},
|
|
|
|
// 取消订阅
|
|
unsubscribeLogs: () => {
|
|
ipcRenderer.removeAllListeners('debug:log');
|
|
ipcRenderer.send('debug:unsubscribe');
|
|
},
|
|
|
|
// 发送日志到主进程
|
|
log: (level: string, source: string, message: string) => {
|
|
ipcRenderer.send('debug:log', { level, source, message });
|
|
},
|
|
},
|
|
});
|