121 lines
3.0 KiB
TypeScript
121 lines
3.0 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
import { TSSClient, createTSSClient, KeygenParams, KeygenResult } from '@/lib/tss';
|
|
|
|
interface UseTSSClientOptions {
|
|
messageRouterUrl?: string;
|
|
autoInit?: boolean;
|
|
}
|
|
|
|
interface UseTSSClientReturn {
|
|
client: TSSClient | null;
|
|
isInitialized: boolean;
|
|
isInitializing: boolean;
|
|
error: string | null;
|
|
init: () => Promise<void>;
|
|
registerParty: (partyId: string, role?: string) => Promise<void>;
|
|
keygen: (
|
|
params: KeygenParams,
|
|
onProgress?: (current: number, total: number) => void
|
|
) => Promise<KeygenResult>;
|
|
stop: () => void;
|
|
disconnect: () => void;
|
|
}
|
|
|
|
const DEFAULT_MESSAGE_ROUTER_URL = 'mpc-grpc.szaiai.com:443';
|
|
|
|
/**
|
|
* React hook for TSS client operations
|
|
*/
|
|
export function useTSSClient(options: UseTSSClientOptions = {}): UseTSSClientReturn {
|
|
const {
|
|
messageRouterUrl = DEFAULT_MESSAGE_ROUTER_URL,
|
|
autoInit = true,
|
|
} = options;
|
|
|
|
const [client, setClient] = useState<TSSClient | null>(null);
|
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
const [isInitializing, setIsInitializing] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const clientRef = useRef<TSSClient | null>(null);
|
|
|
|
const init = useCallback(async () => {
|
|
if (isInitializing || isInitialized) {
|
|
return;
|
|
}
|
|
|
|
setIsInitializing(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const tssClient = createTSSClient(messageRouterUrl);
|
|
await tssClient.init();
|
|
|
|
clientRef.current = tssClient;
|
|
setClient(tssClient);
|
|
setIsInitialized(true);
|
|
} catch (err) {
|
|
const errorMessage = err instanceof Error ? err.message : 'Failed to initialize TSS client';
|
|
setError(errorMessage);
|
|
console.error('TSS client initialization failed:', err);
|
|
} finally {
|
|
setIsInitializing(false);
|
|
}
|
|
}, [messageRouterUrl, isInitializing, isInitialized]);
|
|
|
|
const registerParty = useCallback(async (partyId: string, role: string = 'temporary') => {
|
|
if (!clientRef.current) {
|
|
throw new Error('TSS client not initialized');
|
|
}
|
|
await clientRef.current.registerParty(partyId, role);
|
|
}, []);
|
|
|
|
const keygen = useCallback(async (
|
|
params: KeygenParams,
|
|
onProgress?: (current: number, total: number) => void
|
|
): Promise<KeygenResult> => {
|
|
if (!clientRef.current) {
|
|
throw new Error('TSS client not initialized');
|
|
}
|
|
|
|
return clientRef.current.keygen(params, onProgress, (error) => {
|
|
console.error('Keygen error:', error);
|
|
});
|
|
}, []);
|
|
|
|
const stop = useCallback(() => {
|
|
clientRef.current?.stop();
|
|
}, []);
|
|
|
|
const disconnect = useCallback(() => {
|
|
clientRef.current?.disconnect();
|
|
setClient(null);
|
|
setIsInitialized(false);
|
|
}, []);
|
|
|
|
// Auto-init on mount
|
|
useEffect(() => {
|
|
if (autoInit) {
|
|
init();
|
|
}
|
|
|
|
return () => {
|
|
clientRef.current?.disconnect();
|
|
};
|
|
}, [autoInit, init]);
|
|
|
|
return {
|
|
client,
|
|
isInitialized,
|
|
isInitializing,
|
|
error,
|
|
init,
|
|
registerParty,
|
|
keygen,
|
|
stop,
|
|
disconnect,
|
|
};
|
|
}
|