@nuwa-ai/identity-kit-web
Version:
Web extensions for Nuwa Identity Kit
132 lines (131 loc) • 4.41 kB
JavaScript
import { useState, useEffect, useCallback } from 'react';
import { IdentityKitWeb } from '..';
/**
* React hook for Nuwa Identity Kit (Web)
*/
export function useIdentityKit(options = {}) {
const [sdk, setSdk] = useState(null);
const [state, setState] = useState({
isConnected: false,
isConnecting: false,
agentDid: null,
keyId: null,
error: null,
});
/**
* Helper – refresh connection state from SDK instance
*/
async function refreshConnection(kit = sdk) {
if (!kit)
return;
const isConnected = await kit.isConnected();
if (isConnected) {
const did = await kit.getDid();
const keyIds = await kit.listKeyIds();
setState({
isConnected: true,
isConnecting: false,
agentDid: did,
keyId: keyIds.length > 0 ? keyIds[0] : null,
error: null,
});
}
else {
setState(prev => ({
...prev,
isConnected: false,
isConnecting: false,
}));
}
}
// Initialize SDK
useEffect(() => {
async function initSdk() {
try {
const newSdk = await IdentityKitWeb.init({
appName: options.appName,
cadopDomain: options.cadopDomain,
storage: options.storage,
roochRpcUrl: options.roochRpcUrl,
});
setSdk(newSdk);
// Check connection status
await refreshConnection(newSdk);
}
catch (error) {
setState(prev => ({
...prev,
error: `Failed to initialize SDK: ${error instanceof Error ? error.message : String(error)}`,
}));
}
}
initSdk();
}, [options.appName, options.cadopDomain, options.storage]);
// Listen for postMessage from callback window
useEffect(() => {
function handleMessage(event) {
if (event.data && event.data.type === 'nuwa-auth-success') {
// Re-check connection status when callback signals success
refreshConnection();
}
}
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, [sdk]);
// Auto connect
useEffect(() => {
if (options.autoConnect && sdk && !state.isConnected && !state.isConnecting) {
connect();
}
}, [sdk, options.autoConnect, state.isConnected, state.isConnecting]);
// Connect action
const connect = useCallback(async () => {
if (!sdk) {
setState(prev => ({ ...prev, error: 'SDK not initialized' }));
return;
}
setState(prev => ({ ...prev, isConnecting: true, error: null }));
try {
await sdk.connect();
// Actual connection result will be handled via postMessage in callback
setState(prev => ({ ...prev, isConnecting: false }));
}
catch (error) {
setState({
isConnected: false,
isConnecting: false,
agentDid: null,
keyId: null,
error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
});
}
}, [sdk]);
// Sign operation
const sign = useCallback(async (payload) => {
if (!sdk)
throw new Error('SDK not initialized');
if (!state.isConnected)
throw new Error('Not connected');
return sdk.sign(payload);
}, [sdk, state.isConnected]);
// Verify signature
const verify = useCallback(async (sig) => {
if (!sdk)
throw new Error('SDK not initialized');
return sdk.verify(sig);
}, [sdk]);
// Logout
const logout = useCallback(async () => {
if (!sdk)
throw new Error('SDK not initialized');
await sdk.logout();
setState({
isConnected: false,
isConnecting: false,
agentDid: null,
keyId: null,
error: null,
});
}, [sdk]);
return { state, connect, sign, verify, logout, sdk };
}