// ============================================ // TOKEN AUTHENTICATION MODAL // ============================================ // Модальное окно для авторизации через Web3 токены // Поддерживает покупку, проверку и управление токенами // Enhanced with complete ASN.1 validation // ============================================ const TokenAuthModal = ({ isOpen, onClose, onAuthenticated, tokenAuthManager, web3ContractManager }) => { const [currentStep, setCurrentStep] = React.useState('connect'); // connect, purchase, authenticate, success const [walletAddress, setWalletAddress] = React.useState(''); const [isConnecting, setIsConnecting] = React.useState(false); const [isPurchasing, setIsPurchasing] = React.useState(false); const [isAuthenticating, setIsAuthenticating] = React.useState(false); const [selectedTokenType, setSelectedTokenType] = React.useState('monthly'); const [tokenPrices, setTokenPrices] = React.useState(null); const [userTokens, setUserTokens] = React.useState([]); const [activeToken, setActiveToken] = React.useState(null); const [error, setError] = React.useState(''); const [success, setSuccess] = React.useState(''); // Состояния для разных шагов const [purchaseAmount, setPurchaseAmount] = React.useState(''); const [tokenId, setTokenId] = React.useState(''); React.useEffect(() => { if (isOpen) { initializeModal(); } }, [isOpen]); // Инициализация модального окна const initializeModal = async () => { try { setCurrentStep('connect'); setError(''); setSuccess(''); // Проверяем статус кошелька if (tokenAuthManager && tokenAuthManager.walletAddress) { setWalletAddress(tokenAuthManager.walletAddress); await checkUserTokens(); setCurrentStep('authenticate'); } } catch (error) { console.error('Modal initialization failed:', error); setError('Failed to initialize authentication'); } }; // Подключение кошелька const connectWallet = async () => { try { setIsConnecting(true); setError(''); if (!tokenAuthManager) { throw new Error('Token auth manager not available'); } // Инициализируем Web3 await tokenAuthManager.initialize(); if (tokenAuthManager.walletAddress) { setWalletAddress(tokenAuthManager.walletAddress); await checkUserTokens(); setCurrentStep('authenticate'); } else { throw new Error('Failed to connect wallet'); } } catch (error) { console.error('Wallet connection failed:', error); setError(error.message || 'Failed to connect wallet'); } finally { setIsConnecting(false); } }; // Проверка токенов пользователя const checkUserTokens = async () => { try { if (!web3ContractManager || !walletAddress) return; // Получаем активные токены пользователя const activeTokens = await web3ContractManager.getActiveUserTokens(walletAddress); if (activeTokens.length > 0) { // Получаем информацию о первом активном токене const tokenInfo = await web3ContractManager.getTokenInfo(activeTokens[0]); setActiveToken(tokenInfo); setUserTokens(activeTokens); } } catch (error) { console.error('Failed to check user tokens:', error); } }; // Получение цен токенов const loadTokenPrices = async () => { try { if (!web3ContractManager) return; const prices = await web3ContractManager.getTokenPrices(); setTokenPrices(prices); } catch (error) { console.error('Failed to load token prices:', error); } }; // Покупка токена const purchaseToken = async () => { try { setIsPurchasing(true); setError(''); if (!web3ContractManager || !walletAddress) { throw new Error('Web3 contract manager not available'); } let result; if (selectedTokenType === 'monthly') { result = await web3ContractManager.purchaseMonthlyToken(tokenPrices.monthlyWei); } else { result = await web3ContractManager.purchaseYearlyToken(tokenPrices.yearlyWei); } // Получаем ID токена из события const tokenId = result.events.TokenMinted.returnValues.tokenId; setTokenId(tokenId); setSuccess(`Token purchased successfully! Token ID: ${tokenId}`); setCurrentStep('authenticate'); // Обновляем список токенов await checkUserTokens(); } catch (error) { console.error('Token purchase failed:', error); setError(error.message || 'Failed to purchase token'); } finally { setIsPurchasing(false); } }; // Авторизация через токен const authenticateWithToken = async (tokenId) => { try { setIsAuthenticating(true); setError(''); if (!tokenAuthManager) { throw new Error('Token auth manager not available'); } // Определяем тип токена let tokenType = 'monthly'; if (activeToken) { tokenType = activeToken.tokenType === 0 ? 'monthly' : 'yearly'; } // Авторизуемся через токен const session = await tokenAuthManager.authenticateWithToken(tokenId, tokenType); setSuccess('Authentication successful!'); setCurrentStep('success'); // Вызываем callback if (onAuthenticated) { onAuthenticated(session); } } catch (error) { console.error('Authentication failed:', error); setError(error.message || 'Failed to authenticate'); } finally { setIsAuthenticating(false); } }; // Переключение на шаг покупки const goToPurchase = () => { setCurrentStep('purchase'); loadTokenPrices(); }; // Переключение на шаг авторизации const goToAuthenticate = () => { setCurrentStep('authenticate'); }; // Закрытие модального окна const handleClose = () => { setCurrentStep('connect'); setError(''); setSuccess(''); setTokenId(''); setActiveToken(null); onClose(); }; // Форматирование цены const formatPrice = (price) => { if (!price) return 'Loading...'; return `${parseFloat(price).toFixed(4)} ETH`; }; // Форматирование времени истечения const formatExpiry = (timestamp) => { if (!timestamp) return 'Unknown'; const date = new Date(timestamp * 1000); return date.toLocaleDateString() + ' ' + date.toLocaleTimeString(); }; // Получение названия типа токена const getTokenTypeName = (type) => { return type === 0 ? 'Monthly' : 'Yearly'; }; // Рендер шага подключения const renderConnectStep = () => (
Connect your MetaMask or other Web3 wallet to continue
Choose your subscription plan
{formatPrice(tokenPrices?.monthly)}
30 days access
{formatPrice(tokenPrices?.yearly)}
365 days access
Use your access token to authenticate
Token ID: {activeToken.tokenId}
Type: {getTokenTypeName(activeToken.tokenType)}
Expires: {formatExpiry(activeToken.expiryDate)}
You don't have an active access token. Please purchase one first.
Token ID: {tokenId}
You are now authenticated and can access the service
Secure authentication powered by Web3
Your wallet address: {walletAddress ? `${walletAddress.substring(0, 6)}...${walletAddress.substring(38)}` : 'Not connected'}