import React, { useState, useEffect } from 'react'; import { usePezkuwi } from '@/contexts/PezkuwiContext'; import { useWallet } from '@/contexts/WalletContext'; import { X, AlertCircle, Loader2, CheckCircle, Info } 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 { Input } from '@/components/ui/input'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { useToast } from '@/hooks/use-toast'; import { useTranslation } from 'react-i18next'; interface InitializeUsdtModalProps { isOpen: boolean; onClose: () => void; onSuccess?: () => void; } type TransactionStatus = 'idle' | 'signing' | 'submitting' | 'success' | 'error'; const USDT_ASSET_ID = 1000; // wUSDT asset ID (matches runtime WUSDT_ASSET_ID) const USDT_DECIMALS = 6; // USDT standard decimals export const InitializeUsdtModal: React.FC = ({ isOpen, onClose, onSuccess, }) => { // Use Asset Hub API for DEX operations (assets pallet is on Asset Hub) const { assetHubApi, isAssetHubReady } = usePezkuwi(); const { account, signer } = useWallet(); const { toast } = useToast(); const { t } = useTranslation(); const [usdtAmount, setUsdtAmount] = useState('10000'); const [wusdtBalance, setWusdtBalance] = useState('0'); const [txStatus, setTxStatus] = useState('idle'); const [errorMessage, setErrorMessage] = useState(''); // Reset form when modal closes useEffect(() => { if (!isOpen) { setUsdtAmount('10000'); setTxStatus('idle'); setErrorMessage(''); } }, [isOpen]); // Fetch wUSDT balance from Asset Hub useEffect(() => { const fetchBalance = async () => { if (!assetHubApi || !isAssetHubReady || !account) return; try { // wUSDT balance (asset 1000 on Asset Hub) const wusdtData = await assetHubApi.query.assets.account(USDT_ASSET_ID, account); setWusdtBalance(wusdtData.isSome ? wusdtData.unwrap().balance.toString() : '0'); } catch (error) { if (import.meta.env.DEV) console.error('Failed to fetch wUSDT balance from Asset Hub:', error); } }; fetchBalance(); }, [assetHubApi, isAssetHubReady, account]); const handleMint = async () => { if (!assetHubApi || !isAssetHubReady || !signer || !account) { toast({ title: t('common.error'), description: t('mint.connectWallet'), variant: 'destructive', }); return; } // Check if assets pallet is available on Asset Hub if (!assetHubApi.tx.assets || !assetHubApi.tx.assets.mint) { setErrorMessage(t('mint.palletNotAvailable')); toast({ title: t('mint.palletToast'), description: t('mint.palletToastDesc'), variant: 'destructive', }); return; } const usdtAmountRaw = BigInt(parseFloat(usdtAmount) * 10 ** USDT_DECIMALS); if (usdtAmountRaw <= BigInt(0)) { setErrorMessage(t('common.amountGtZero')); return; } setTxStatus('signing'); setErrorMessage(''); try { if (import.meta.env.DEV) console.log('💵 Minting wUSDT on Asset Hub...', { usdtAmount, usdtAmountRaw: usdtAmountRaw.toString(), assetId: USDT_ASSET_ID, }); const mintTx = assetHubApi.tx.assets.mint(USDT_ASSET_ID, account, usdtAmountRaw.toString()); setTxStatus('submitting'); await mintTx.signAndSend( account, { signer }, ({ status, dispatchError, events }) => { if (import.meta.env.DEV) console.log('📦 Transaction status:', status.type); if (status.isInBlock) { if (import.meta.env.DEV) console.log('✅ In block:', status.asInBlock.toHex()); if (dispatchError) { let errorMsg = ''; if (dispatchError.isModule) { const decoded = assetHubApi.registry.findMetaError(dispatchError.asModule); errorMsg = `${decoded.section}.${decoded.name}: ${decoded.docs.join(' ')}`; if (import.meta.env.DEV) console.error('❌ Module error:', errorMsg); } else { errorMsg = dispatchError.toString(); if (import.meta.env.DEV) console.error('❌ Dispatch error:', errorMsg); } setErrorMessage(errorMsg); setTxStatus('error'); toast({ title: t('common.txFailed'), description: errorMsg, variant: 'destructive', }); } else { if (import.meta.env.DEV) console.log('✅ Mint successful!'); if (import.meta.env.DEV) console.log('📋 Events:', events.map(e => e.event.method).join(', ')); setTxStatus('success'); toast({ title: t('common.success'), description: t('mintUsdt.minted', { amount: usdtAmount }), }); setTimeout(() => { onSuccess?.(); onClose(); }, 2000); } } } ); } catch (error) { if (import.meta.env.DEV) console.error('Mint failed:', error); setErrorMessage(error instanceof Error ? error.message : t('common.txFailed')); setTxStatus('error'); toast({ title: t('common.error'), description: error instanceof Error ? error.message : t('common.txFailed'), variant: 'destructive', }); } }; if (!isOpen) return null; const wusdtBalanceDisplay = (parseFloat(wusdtBalance) / 10 ** USDT_DECIMALS).toFixed(2); return (
{t('mintUsdt.title')}
{t('mintUsdt.adminOnly')}
{/* Info Banner */} {t('mintUsdt.info')} {/* USDT Amount */}
{t('mint.current')} {wusdtBalanceDisplay} wUSDT
setUsdtAmount(e.target.value)} placeholder="10000" className="w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-white text-lg" disabled={txStatus === 'signing' || txStatus === 'submitting'} />

{t('mintUsdt.decimalsInfo')}

{/* Current wUSDT Balance */}
{t('mintUsdt.currentBalance')}
{wusdtBalanceDisplay} wUSDT
{/* Error Message */} {errorMessage && ( {errorMessage} )} {/* Success Message */} {txStatus === 'success' && ( {t('mintUsdt.success', { amount: usdtAmount })} )} {/* Action Buttons */}
); };