// 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 { 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, }) => { const { api, isApiReady } = usePezkuwi(); const { account, signer } = useWallet(); const { toast } = useToast(); // 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 (!api || !isApiReady) return; setStep('checking'); setStatusMessage('Checking bridge status...'); setErrorMessage(''); try { // Check current bridge status const status = await checkBridgeStatus(api); setBridgeStatus(status); // Fetch Asset Hub USDT info setStatusMessage('Fetching Asset Hub USDT info...'); const info = await fetchAssetHubUsdtInfo(); setAssetHubInfo(info); setStatusMessage('Status check complete'); setStep('idle'); } catch (error) { console.error('Initial check failed:', error); setErrorMessage(error instanceof Error ? error.message : 'Status check failed'); setStep('error'); } }, [api, isApiReady]); // Reset when modal opens/closes useEffect(() => { if (!isOpen) { setStep('idle'); setStatusMessage(''); setErrorMessage(''); setShowPoolCreation(false); } else { // Auto-check status when opened if (api && isApiReady && account) { performInitialCheck(); } } }, [isOpen, api, isApiReady, account, performInitialCheck]); /** * Configure XCM bridge */ const handleConfigureBridge = async () => { if (!api || !isApiReady || !signer || !account) { toast({ title: 'Error', description: 'Please connect your wallet', variant: 'destructive', }); return; } setStep('configuring'); setErrorMessage(''); try { await configureXcmBridge( api, signer, account, (status) => setStatusMessage(status) ); toast({ title: 'Success!', description: 'XCM bridge configured successfully', }); // Refresh status await performInitialCheck(); setStep('success'); setStatusMessage('Bridge configuration complete!'); } catch (error) { console.error('Bridge configuration failed:', error); setErrorMessage(error instanceof Error ? error.message : 'Configuration failed'); setStep('error'); toast({ title: 'Configuration Failed', description: error instanceof Error ? error.message : 'Unknown error', variant: 'destructive', }); } }; /** * Create wUSDT/HEZ pool */ const handleCreatePool = async () => { if (!api || !isApiReady || !signer || !account) { toast({ title: 'Error', description: 'Please connect your wallet', 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( api, signer, account, wusdtRaw, hezRaw, (status) => setStatusMessage(status) ); toast({ title: 'Success!', description: 'wUSDT/HEZ pool created successfully', }); setStep('success'); setStatusMessage('Pool creation complete!'); 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: 'Pool Creation Failed', description: error instanceof Error ? error.message : 'Unknown error', variant: 'destructive', }); } }; if (!isOpen) return null; const isLoading = step === 'checking' || step === 'fetching' || step === 'configuring' || step === 'pool-creation'; return (
XCM Bridge Setup
Admin Only - XCM Configuration
{/* Info Banner */} Configure Asset Hub USDT → wUSDT bridge with one click. This enables cross-chain transfers from Westend Asset Hub to PezkuwiChain. {/* Current Status */} {bridgeStatus && (
Current Status
Asset Hub Connection:
{bridgeStatus.assetHubConnected ? ( ) : ( )} {bridgeStatus.assetHubConnected ? 'Connected' : 'Checking...'}
wUSDT Asset Exists:
{bridgeStatus.wusdtExists ? ( ) : ( )} {bridgeStatus.wusdtExists ? 'Yes (ID: 1000)' : 'Not Found'}
XCM Bridge Configured:
{bridgeStatus.isConfigured ? ( ) : ( )} {bridgeStatus.isConfigured ? 'Configured' : 'Not Configured'}
)} {/* Asset Hub USDT Info */} {assetHubInfo && (
Asset Hub USDT Info
Asset ID: {assetHubInfo.id} Symbol: {assetHubInfo.symbol} Decimals: {assetHubInfo.decimals} Total Supply: {(parseFloat(assetHubInfo.supply) / 10 ** 6).toLocaleString()} USDT
View on Subscan
)} {/* Configuration Details */}
Configuration Details
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 && (
Create wUSDT/HEZ Pool (Optional)
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 */}
⚠️ XCM bridge configuration requires sudo access
); };