// Force reload for mock XCM update import React, { useState, useEffect, useCallback } from 'react'; import { usePezkuwi } from '@/contexts/PezkuwiContext'; import { useWallet } from '@/contexts/WalletContext'; import { X, AlertCircle, Loader2, CheckCircle, Info, ExternalLink, Zap } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { useToast } from '@/hooks/use-toast'; import { useTranslation } from 'react-i18next'; import { checkBridgeStatus, fetchAssetHubUsdtInfo, configureXcmBridge, createWUsdtHezPool, ASSET_HUB_USDT_ID, WUSDT_ASSET_ID, ASSET_HUB_ENDPOINT, type BridgeStatus, type AssetHubUsdtInfo, } from '@pezkuwi/lib/xcm-bridge'; interface XCMBridgeSetupModalProps { isOpen: boolean; onClose: () => void; onSuccess?: () => void; } type SetupStep = 'idle' | 'checking' | 'fetching' | 'configuring' | 'pool-creation' | 'success' | 'error'; export const XCMBridgeSetupModal: React.FC = ({ isOpen, onClose, onSuccess, }) => { // Use Asset Hub API for DEX operations const { assetHubApi, isAssetHubReady } = usePezkuwi(); const { account, signer } = useWallet(); const { toast } = useToast(); const { t } = useTranslation(); // State const [step, setStep] = useState('idle'); const [bridgeStatus, setBridgeStatus] = useState(null); const [assetHubInfo, setAssetHubInfo] = useState(null); const [statusMessage, setStatusMessage] = useState(''); const [errorMessage, setErrorMessage] = useState(''); const [showPoolCreation, setShowPoolCreation] = useState(false); const [wusdtAmount, setWusdtAmount] = useState('1000'); const [hezAmount, setHezAmount] = useState('10'); /** * Perform initial status check */ const performInitialCheck = useCallback(async () => { if (!assetHubApi || !isAssetHubReady) return; setStep('checking'); setStatusMessage(t('xcmBridge.checkingStatus')); setErrorMessage(''); try { // Check current bridge status const status = await checkBridgeStatus(assetHubApi); setBridgeStatus(status); // Fetch Asset Hub USDT info setStatusMessage(t('xcmBridge.fetchingInfo')); const info = await fetchAssetHubUsdtInfo(); setAssetHubInfo(info); setStatusMessage(t('xcmBridge.statusComplete')); setStep('idle'); } catch (error) { console.error('Initial check failed:', error); setErrorMessage(error instanceof Error ? error.message : 'Status check failed'); setStep('error'); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [assetHubApi, isAssetHubReady]); // Reset when modal opens/closes useEffect(() => { if (!isOpen) { setStep('idle'); setStatusMessage(''); setErrorMessage(''); setShowPoolCreation(false); } else { // Auto-check status when opened if (assetHubApi && isAssetHubReady && account) { performInitialCheck(); } } }, [isOpen, assetHubApi, isAssetHubReady, account, performInitialCheck]); /** * Configure XCM bridge */ const handleConfigureBridge = async () => { if (!assetHubApi || !isAssetHubReady || !signer || !account) { toast({ title: t('common.error'), description: t('common.connectWalletAlert'), variant: 'destructive', }); return; } setStep('configuring'); setErrorMessage(''); try { await configureXcmBridge( assetHubApi, signer, account, (status) => setStatusMessage(status) ); toast({ title: t('common.success'), description: t('xcmBridge.bridgeConfigured'), }); // Refresh status await performInitialCheck(); setStep('success'); setStatusMessage(t('xcmBridge.configComplete')); } catch (error) { console.error('Bridge configuration failed:', error); setErrorMessage(error instanceof Error ? error.message : 'Configuration failed'); setStep('error'); toast({ title: t('xcmBridge.configFailed'), description: error instanceof Error ? error.message : t('common.error'), variant: 'destructive', }); } }; /** * Create wUSDT/HEZ pool */ const handleCreatePool = async () => { if (!assetHubApi || !isAssetHubReady || !signer || !account) { toast({ title: t('common.error'), description: t('common.connectWalletAlert'), variant: 'destructive', }); return; } setStep('pool-creation'); setErrorMessage(''); try { // Convert amounts to raw values (6 decimals for wUSDT, 12 for HEZ) const wusdtRaw = BigInt(parseFloat(wusdtAmount) * 10 ** 6).toString(); const hezRaw = BigInt(parseFloat(hezAmount) * 10 ** 12).toString(); await createWUsdtHezPool( assetHubApi, signer, account, wusdtRaw, hezRaw, (status) => setStatusMessage(status) ); toast({ title: t('common.success'), description: t('xcmBridge.poolCreated'), }); setStep('success'); setStatusMessage(t('xcmBridge.poolComplete')); setTimeout(() => { onSuccess?.(); onClose(); }, 2000); } catch (error) { console.error('Pool creation failed:', error); setErrorMessage(error instanceof Error ? error.message : 'Pool creation failed'); setStep('error'); toast({ title: t('xcmBridge.poolFailed'), description: error instanceof Error ? error.message : t('common.error'), variant: 'destructive', }); } }; if (!isOpen) return null; const isLoading = step === 'checking' || step === 'fetching' || step === 'configuring' || step === 'pool-creation'; return (
{t('xcmBridge.title')}
{t('xcmBridge.adminOnly')}
{/* Info Banner */} {t('xcmBridge.info')} {/* Current Status */} {bridgeStatus && (
{t('xcmBridge.currentStatus')}
{t('xcmBridge.assetHubConnection')}
{bridgeStatus.assetHubConnected ? ( ) : ( )} {bridgeStatus.assetHubConnected ? t('xcmBridge.connected') : t('xcmBridge.checking')}
{t('xcmBridge.wusdtAssetExists')}
{bridgeStatus.wusdtExists ? ( ) : ( )} {bridgeStatus.wusdtExists ? t('xcmBridge.yesId') : t('xcmBridge.notFound')}
{t('xcmBridge.xcmConfigured')}
{bridgeStatus.isConfigured ? ( ) : ( )} {bridgeStatus.isConfigured ? t('xcmBridge.configured') : t('xcmBridge.notConfigured')}
)} {/* Asset Hub USDT Info */} {assetHubInfo && (
{t('xcmBridge.assetHubInfo')}
Asset ID: {assetHubInfo.id} Symbol: {assetHubInfo.symbol} Decimals: {assetHubInfo.decimals} Total Supply: {(parseFloat(assetHubInfo.supply) / 10 ** 6).toLocaleString()} USDT
View on Subscan
)} {/* Configuration Details */}
{t('xcmBridge.configDetails')}
Asset Hub Endpoint: {ASSET_HUB_ENDPOINT}
Asset Hub USDT ID: {ASSET_HUB_USDT_ID}
PezkuwiChain wUSDT ID: {WUSDT_ASSET_ID}
Parachain ID: 1000 (Asset Hub)
{/* Status Message */} {statusMessage && ( {statusMessage} )} {/* Error Message */} {errorMessage && ( {errorMessage} )} {/* Success Message */} {step === 'success' && ( {statusMessage} )} {/* Pool Creation Section (Optional) */} {showPoolCreation && (
{t('xcmBridge.createPoolSection')}
setWusdtAmount(e.target.value)} className="w-full px-3 py-2 bg-gray-800 border border-gray-700 rounded text-white text-sm" placeholder="1000" />
setHezAmount(e.target.value)} className="w-full px-3 py-2 bg-gray-800 border border-gray-700 rounded text-white text-sm" placeholder="10" />
)} {/* Action Buttons */}
{!bridgeStatus?.isConfigured && ( )} {bridgeStatus?.isConfigured && !showPoolCreation && ( )} {showPoolCreation && ( )}
{/* Note */}
{t('xcmBridge.sudoWarning')}
); };