// DeFi Platform JavaScript Functionality document.addEventListener('DOMContentLoaded', function() { // Initialize tooltips var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); // =============== LENDING & BORROWING TAB =============== // Lending form calculations const lendingAmountInput = document.getElementById('lendingAmount'); const lendingAssetSelect = document.getElementById('lendingAsset'); const lendingTermSelect = document.getElementById('lendingTerm'); const estimatedReturnsElement = document.getElementById('estimatedReturns'); const totalReturnElement = document.getElementById('totalReturn'); if (lendingAmountInput && lendingAssetSelect && lendingTermSelect) { const calculateLendingReturns = () => { const amount = parseFloat(lendingAmountInput.value) || 0; const asset = lendingAssetSelect.value; const termDays = parseInt(lendingTermSelect.value) || 30; // Get APY from the selected option's text const selectedOption = lendingTermSelect.options[lendingTermSelect.selectedIndex]; const apyMatch = selectedOption.text.match(/\((\d+\.\d+)%\)/); const apy = apyMatch ? parseFloat(apyMatch[1]) / 100 : 0.05; // Default to 5% if not found // Calculate returns (simple interest for demonstration) const returns = amount * apy * (termDays / 365); const total = amount + returns; if (estimatedReturnsElement) { estimatedReturnsElement.textContent = returns.toFixed(2) + ' ' + asset; } if (totalReturnElement) { totalReturnElement.textContent = total.toFixed(2) + ' ' + asset; } }; lendingAmountInput.addEventListener('input', calculateLendingReturns); lendingAssetSelect.addEventListener('change', calculateLendingReturns); lendingTermSelect.addEventListener('change', calculateLendingReturns); } // Borrowing form calculations const borrowingAmountInput = document.getElementById('borrowingAmount'); const borrowingAssetSelect = document.getElementById('borrowingAsset'); const borrowingTermSelect = document.getElementById('borrowingTerm'); const borrowingCollateralSelect = document.getElementById('collateralAsset'); const borrowingCollateralAmountInput = document.getElementById('collateralAmount'); const interestDueElement = document.getElementById('interestDue'); const totalRepaymentElement = document.getElementById('totalRepayment'); const borrowingCollateralRatioElement = document.getElementById('collateralRatio'); if (borrowingAmountInput && borrowingAssetSelect && borrowingCollateralSelect && borrowingCollateralAmountInput) { const calculateBorrowingDetails = () => { const amount = parseFloat(borrowingAmountInput.value) || 0; const asset = borrowingAssetSelect.value; const termDays = parseInt(borrowingTermSelect.value) || 30; // Get APR from the selected option's text const selectedOption = borrowingTermSelect.options[borrowingTermSelect.selectedIndex]; const aprMatch = selectedOption.text.match(/\((\d+\.\d+)%\)/); const apr = aprMatch ? parseFloat(aprMatch[1]) / 100 : 0.08; // Default to 8% if not found // Calculate interest and total repayment const interest = amount * apr * (termDays / 365); const total = amount + interest; if (interestDueElement) { interestDueElement.textContent = interest.toFixed(2) + ' ' + asset; } if (totalRepaymentElement) { totalRepaymentElement.textContent = total.toFixed(2) + ' ' + asset; } // Calculate collateral ratio const collateralAmount = parseFloat(borrowingCollateralAmountInput.value) || 0; const collateralAsset = borrowingCollateralSelect.value; let collateralValue = 0; // Mock prices for demonstration const assetPrices = { 'TFT': 0.5, 'ZAZ': 0.5, 'USDT': 1.0 }; if (collateralAsset in assetPrices) { collateralValue = collateralAmount * assetPrices[collateralAsset]; } else { // For other assets, assume the value is the amount (simplified) collateralValue = collateralAmount; } const borrowValue = amount * (asset === 'USDT' ? 1 : assetPrices[asset] || 0.5); const ratio = borrowValue > 0 ? (collateralValue / borrowValue * 100) : 0; if (borrowingCollateralRatioElement) { borrowingCollateralRatioElement.textContent = ratio.toFixed(0) + '%'; // Update color based on ratio if (ratio >= 200) { borrowingCollateralRatioElement.className = 'text-success'; } else if (ratio >= 150) { borrowingCollateralRatioElement.className = 'text-warning'; } else { borrowingCollateralRatioElement.className = 'text-danger'; } } }; borrowingAmountInput.addEventListener('input', calculateBorrowingDetails); borrowingAssetSelect.addEventListener('change', calculateBorrowingDetails); borrowingTermSelect.addEventListener('change', calculateBorrowingDetails); borrowingCollateralSelect.addEventListener('change', calculateBorrowingDetails); borrowingCollateralAmountInput.addEventListener('input', calculateBorrowingDetails); } // =============== LIQUIDITY POOLS TAB =============== // Add Liquidity form calculations const poolSelect = document.getElementById('liquidityPool'); const token1AmountInput = document.getElementById('token1Amount'); const token2AmountInput = document.getElementById('token2Amount'); const lpTokensElement = document.getElementById('lpTokensReceived'); const poolShareElement = document.getElementById('poolShare'); if (poolSelect && token1AmountInput && token2AmountInput) { const calculateLiquidityDetails = () => { const token1Amount = parseFloat(token1AmountInput.value) || 0; const token2Amount = parseFloat(token2AmountInput.value) || 0; // Mock calculations for demonstration const lpTokens = Math.sqrt(token1Amount * token2Amount); const poolShare = token1Amount > 0 ? (lpTokens / (lpTokens + 1000) * 100) : 0; if (lpTokensElement) { lpTokensElement.textContent = lpTokens.toFixed(2); } if (poolShareElement) { poolShareElement.textContent = poolShare.toFixed(2) + '%'; } }; token1AmountInput.addEventListener('input', calculateLiquidityDetails); token2AmountInput.addEventListener('input', calculateLiquidityDetails); // Handle pool selection to update token labels poolSelect.addEventListener('change', function() { const selectedOption = poolSelect.options[poolSelect.selectedIndex]; const token1Label = document.getElementById('token1Label'); const token2Label = document.getElementById('token2Label'); if (selectedOption.value === 'tft-zaz') { if (token1Label) token1Label.textContent = 'TFT'; if (token2Label) token2Label.textContent = 'ZAZ'; } else if (selectedOption.value === 'zaz-usdt') { if (token1Label) token1Label.textContent = 'ZAZ'; if (token2Label) token2Label.textContent = 'USDT'; } calculateLiquidityDetails(); }); } // =============== STAKING TAB =============== // TFT Staking calculations const tftStakeAmountInput = document.getElementById('tftStakeAmount'); const tftStakingPeriodSelect = document.getElementById('tftStakingPeriod'); const tftEstimatedRewardsElement = document.getElementById('tftEstimatedRewards'); if (tftStakeAmountInput && tftStakingPeriodSelect && tftEstimatedRewardsElement) { const calculateTftStakingRewards = () => { const amount = parseFloat(tftStakeAmountInput.value) || 0; const termDays = parseInt(tftStakingPeriodSelect.value) || 30; // Get APY from the selected option's text const selectedOption = tftStakingPeriodSelect.options[tftStakingPeriodSelect.selectedIndex]; const apyMatch = selectedOption.text.match(/\((\d+\.\d+)%\)/); const apy = apyMatch ? parseFloat(apyMatch[1]) / 100 : 0.085; // Default to 8.5% if not found // Calculate rewards (simple interest for demonstration) const rewards = amount * apy * (termDays / 365); tftEstimatedRewardsElement.textContent = rewards.toFixed(2) + ' TFT'; }; tftStakeAmountInput.addEventListener('input', calculateTftStakingRewards); tftStakingPeriodSelect.addEventListener('change', calculateTftStakingRewards); } // ZAZ Staking calculations const zazStakeAmountInput = document.getElementById('zazStakeAmount'); const zazStakingPeriodSelect = document.getElementById('zazStakingPeriod'); const zazEstimatedRewardsElement = document.getElementById('zazEstimatedRewards'); if (zazStakeAmountInput && zazStakingPeriodSelect && zazEstimatedRewardsElement) { const calculateZazStakingRewards = () => { const amount = parseFloat(zazStakeAmountInput.value) || 0; const termDays = parseInt(zazStakingPeriodSelect.value) || 30; // Get APY from the selected option's text const selectedOption = zazStakingPeriodSelect.options[zazStakingPeriodSelect.selectedIndex]; const apyMatch = selectedOption.text.match(/\((\d+\.\d+)%\)/); const apy = apyMatch ? parseFloat(apyMatch[1]) / 100 : 0.12; // Default to 12% if not found // Calculate rewards (simple interest for demonstration) const rewards = amount * apy * (termDays / 365); zazEstimatedRewardsElement.textContent = rewards.toFixed(2) + ' ZAZ'; }; zazStakeAmountInput.addEventListener('input', calculateZazStakingRewards); zazStakingPeriodSelect.addEventListener('change', calculateZazStakingRewards); } // Asset Staking calculations const assetStakingSelect = document.getElementById('assetStaking'); const assetStakingPeriodSelect = document.getElementById('assetStakingPeriod'); const assetEstimatedRewardsElement = document.getElementById('assetEstimatedRewards'); if (assetStakingSelect && assetStakingPeriodSelect && assetEstimatedRewardsElement) { const calculateAssetStakingRewards = () => { const selectedOption = assetStakingSelect.options[assetStakingSelect.selectedIndex]; if (selectedOption.value === '') return; const assetValue = parseFloat(selectedOption.dataset.value) || 0; const termDays = parseInt(assetStakingPeriodSelect.value) || 30; // Get APY from the selected option's text const periodOption = assetStakingPeriodSelect.options[assetStakingPeriodSelect.selectedIndex]; const apyMatch = periodOption.text.match(/\((\d+\.\d+)%\)/); const apy = apyMatch ? parseFloat(apyMatch[1]) / 100 : 0.035; // Default to 3.5% if not found // Calculate rewards in USD (simple interest for demonstration) const rewards = assetValue * apy * (termDays / 365); assetEstimatedRewardsElement.textContent = '$' + rewards.toFixed(2); }; assetStakingSelect.addEventListener('change', calculateAssetStakingRewards); assetStakingPeriodSelect.addEventListener('change', calculateAssetStakingRewards); } // =============== SWAP TAB =============== // Token swap calculations const swapFromAmountInput = document.getElementById('swapFromAmount'); const swapToAmountElement = document.getElementById('swapToAmount'); const fromTokenDropdown = document.getElementById('fromTokenDropdown'); const toTokenDropdown = document.getElementById('toTokenDropdown'); const exchangeRateElement = document.getElementById('exchangeRate'); const minimumReceivedElement = document.getElementById('minimumReceived'); const priceImpactElement = document.getElementById('priceImpact'); const swapDirectionButton = document.getElementById('swapDirectionButton'); const maxFromButton = document.getElementById('maxFromButton'); const fromTokenSymbolElement = document.getElementById('fromTokenSymbol'); const toTokenSymbolElement = document.getElementById('toTokenSymbol'); const fromTokenImgElement = document.getElementById('fromTokenImg'); const toTokenImgElement = document.getElementById('toTokenImg'); const fromTokenBalanceElement = document.getElementById('fromTokenBalance'); const toTokenBalanceElement = document.getElementById('toTokenBalance'); // Mock token data const tokenData = { 'TFT': { price: 0.5, balance: '10,000 TFT', usdValue: '5,000.00' }, 'ZAZ': { price: 0.5, balance: '5,000 ZAZ', usdValue: '2,500.00' }, 'USDT': { price: 1.0, balance: '2,500 USDT', usdValue: '2,500.00' } }; if (swapFromAmountInput && swapToAmountElement) { let fromToken = 'TFT'; let toToken = 'ZAZ'; const calculateSwap = () => { const fromAmount = parseFloat(swapFromAmountInput.value) || 0; // Calculate exchange rate const fromPrice = tokenData[fromToken].price; const toPrice = tokenData[toToken].price; const rate = fromPrice / toPrice; // Calculate to amount const toAmount = fromAmount * rate; // Update UI swapToAmountElement.value = toAmount.toFixed(2); if (exchangeRateElement) { exchangeRateElement.textContent = `1 ${fromToken} = ${rate.toFixed(4)} ${toToken}`; } if (minimumReceivedElement) { // 0.5% slippage for demonstration const minReceived = toAmount * 0.995; minimumReceivedElement.textContent = `${minReceived.toFixed(2)} ${toToken}`; } if (priceImpactElement) { // Mock price impact calculation const impact = fromAmount > 1000 ? '0.5%' : '< 0.1%'; priceImpactElement.textContent = impact; priceImpactElement.className = fromAmount > 1000 ? 'text-warning' : 'text-success'; } }; // Initialize from token dropdown items const fromTokenItems = document.querySelectorAll('[aria-labelledby="fromTokenDropdown"] .dropdown-item'); fromTokenItems.forEach(item => { item.addEventListener('click', function(e) { e.preventDefault(); fromToken = this.dataset.token; fromTokenSymbolElement.textContent = fromToken; fromTokenImgElement.src = this.dataset.img; fromTokenBalanceElement.textContent = tokenData[fromToken].balance; calculateSwap(); }); }); // Initialize to token dropdown items const toTokenItems = document.querySelectorAll('[aria-labelledby="toTokenDropdown"] .dropdown-item'); toTokenItems.forEach(item => { item.addEventListener('click', function(e) { e.preventDefault(); toToken = this.dataset.token; toTokenSymbolElement.textContent = toToken; toTokenImgElement.src = this.dataset.img; toTokenBalanceElement.textContent = tokenData[toToken].balance; calculateSwap(); }); }); // Swap direction button if (swapDirectionButton) { swapDirectionButton.addEventListener('click', function() { // Swap tokens const tempToken = fromToken; fromToken = toToken; toToken = tempToken; // Update UI fromTokenSymbolElement.textContent = fromToken; toTokenSymbolElement.textContent = toToken; const tempImg = fromTokenImgElement.src; fromTokenImgElement.src = toTokenImgElement.src; toTokenImgElement.src = tempImg; fromTokenBalanceElement.textContent = tokenData[fromToken].balance; toTokenBalanceElement.textContent = tokenData[toToken].balance; // Swap amounts const tempAmount = swapFromAmountInput.value; swapFromAmountInput.value = swapToAmountElement.value; calculateSwap(); }); } // Max button if (maxFromButton) { maxFromButton.addEventListener('click', function() { // Set max amount based on token balance const balance = parseInt(tokenData[fromToken].balance.split(' ')[0].replace(/,/g, '')); swapFromAmountInput.value = balance; calculateSwap(); }); } swapFromAmountInput.addEventListener('input', calculateSwap); // Initial calculation calculateSwap(); } // =============== COLLATERAL TAB =============== // Collateral form calculations const collateralAssetSelect = document.getElementById('collateralAsset'); const collateralAmountInput = document.getElementById('collateralAmount'); const collateralValueElement = document.getElementById('collateralValue'); const collateralUnitElement = document.getElementById('collateralUnit'); const collateralAvailableElement = document.getElementById('collateralAvailable'); const collateralAvailableUSDElement = document.getElementById('collateralAvailableUSD'); const collateralPurposeSelect = document.getElementById('collateralPurpose'); const loanTermGroup = document.getElementById('loanTermGroup'); const loanAmountGroup = document.getElementById('loanAmountGroup'); const syntheticAssetGroup = document.getElementById('syntheticAssetGroup'); const syntheticAmountGroup = document.getElementById('syntheticAmountGroup'); const loanAmountInput = document.getElementById('loanAmount'); const maxLoanAmountElement = document.getElementById('maxLoanAmount'); const syntheticAmountInput = document.getElementById('syntheticAmount'); const maxSyntheticAmountElement = document.getElementById('maxSyntheticAmount'); const collateralRatioElement = document.getElementById('collateralRatio'); const liquidationPriceElement = document.getElementById('liquidationPrice'); const liquidationUnitElement = document.getElementById('liquidationUnit'); if (collateralAssetSelect && collateralAmountInput) { const calculateCollateralDetails = () => { if (collateralAssetSelect.selectedIndex === 0) return; const selectedOption = collateralAssetSelect.options[collateralAssetSelect.selectedIndex]; const assetType = selectedOption.dataset.type; const assetValue = parseFloat(selectedOption.dataset.value) || 0; const assetAmount = parseFloat(selectedOption.dataset.amount) || 0; const assetUnit = selectedOption.dataset.unit || ''; // Update UI with asset details if (collateralUnitElement) collateralUnitElement.textContent = assetUnit; if (collateralAvailableElement) collateralAvailableElement.textContent = assetAmount.toLocaleString() + ' ' + assetUnit; if (collateralAvailableUSDElement) collateralAvailableUSDElement.textContent = '$' + assetValue.toLocaleString(); if (liquidationUnitElement) liquidationUnitElement.textContent = assetUnit; // Calculate collateral value const amount = parseFloat(collateralAmountInput.value) || 0; let collateralValue = 0; if (assetType === 'token') { // For tokens, calculate based on token price const tokenPrice = assetValue / assetAmount; collateralValue = amount * tokenPrice; } else { // For NFTs and other assets, use the full value if amount is 1 collateralValue = amount === 1 ? assetValue : 0; } if (collateralValueElement) collateralValueElement.value = collateralValue.toFixed(2); // Calculate max loan amount (75% of collateral value) const maxLoanAmount = collateralValue * 0.75; if (maxLoanAmountElement) maxLoanAmountElement.textContent = maxLoanAmount.toFixed(2); // Calculate max synthetic amount (50% of collateral value) const maxSyntheticAmount = collateralValue * 0.5; if (maxSyntheticAmountElement) maxSyntheticAmountElement.textContent = maxSyntheticAmount.toFixed(2); // Calculate collateral ratio and liquidation price updateCollateralRatio(); }; const updateCollateralRatio = () => { const collateralValue = parseFloat(collateralValueElement.value) || 0; const purpose = collateralPurposeSelect.value; let borrowedValue = 0; if (purpose === 'loan') { borrowedValue = parseFloat(loanAmountInput.value) || 0; } else if (purpose === 'synthetic') { borrowedValue = parseFloat(syntheticAmountInput.value) || 0; } else { // For leverage trading, assume 2x leverage borrowedValue = collateralValue; } // Calculate ratio const ratio = borrowedValue > 0 ? (collateralValue / borrowedValue * 100) : 0; if (collateralRatioElement) { collateralRatioElement.value = ratio.toFixed(0) + '%'; } // Calculate liquidation price if (liquidationPriceElement) { const selectedOption = collateralAssetSelect.options[collateralAssetSelect.selectedIndex]; if (selectedOption.selectedIndex === 0) return; const assetType = selectedOption.dataset.type; const assetValue = parseFloat(selectedOption.dataset.value) || 0; const assetAmount = parseFloat(selectedOption.dataset.amount) || 0; const collateralAmount = parseFloat(collateralAmountInput.value) || 0; if (assetType === 'token' && collateralAmount > 0) { const currentPrice = assetValue / assetAmount; const liquidationThreshold = purpose === 'loan' ? 1.2 : 1.5; // 120% for loans, 150% for synthetic const liquidationPrice = (borrowedValue / collateralAmount) * liquidationThreshold; liquidationPriceElement.value = liquidationPrice.toFixed(4); } else { liquidationPriceElement.value = (borrowedValue * 1.2).toFixed(2); } } }; // Handle collateral asset selection collateralAssetSelect.addEventListener('change', function() { collateralAmountInput.value = ''; calculateCollateralDetails(); }); // Handle collateral amount input collateralAmountInput.addEventListener('input', calculateCollateralDetails); // Handle purpose selection collateralPurposeSelect.addEventListener('change', function() { const purpose = collateralPurposeSelect.value; // Show/hide relevant form groups if (loanTermGroup) loanTermGroup.style.display = purpose === 'loan' ? 'block' : 'none'; if (loanAmountGroup) loanAmountGroup.style.display = purpose === 'loan' ? 'block' : 'none'; if (syntheticAssetGroup) syntheticAssetGroup.style.display = purpose === 'synthetic' ? 'block' : 'none'; if (syntheticAmountGroup) syntheticAmountGroup.style.display = purpose === 'synthetic' ? 'block' : 'none'; updateCollateralRatio(); }); // Handle loan amount input if (loanAmountInput) { loanAmountInput.addEventListener('input', updateCollateralRatio); // Max loan button const maxLoanButton = document.getElementById('maxLoanButton'); if (maxLoanButton) { maxLoanButton.addEventListener('click', function() { const maxLoan = parseFloat(maxLoanAmountElement.textContent) || 0; loanAmountInput.value = maxLoan.toFixed(2); updateCollateralRatio(); }); } } // Handle synthetic amount input if (syntheticAmountInput) { syntheticAmountInput.addEventListener('input', updateCollateralRatio); // Max synthetic button const maxSyntheticButton = document.getElementById('maxSyntheticButton'); if (maxSyntheticButton) { maxSyntheticButton.addEventListener('click', function() { const maxSynthetic = parseFloat(maxSyntheticAmountElement.textContent) || 0; syntheticAmountInput.value = maxSynthetic.toFixed(2); updateCollateralRatio(); }); } } // Handle synthetic asset selection const syntheticAssetSelect = document.getElementById('syntheticAsset'); const syntheticUnitElement = document.getElementById('syntheticUnit'); const maxSyntheticUnitElement = document.getElementById('maxSyntheticUnit'); if (syntheticAssetSelect && syntheticUnitElement && maxSyntheticUnitElement) { syntheticAssetSelect.addEventListener('change', function() { const asset = syntheticAssetSelect.value; syntheticUnitElement.textContent = asset; maxSyntheticUnitElement.textContent = asset; }); } } // Initialize tab functionality if not already handled by Bootstrap const tabLinks = document.querySelectorAll('.nav-link[data-bs-toggle="tab"]'); tabLinks.forEach(tabLink => { tabLink.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); const targetTab = document.querySelector(targetId); // Hide all tabs document.querySelectorAll('.tab-pane').forEach(tab => { tab.classList.remove('show', 'active'); }); // Show the target tab if (targetTab) { targetTab.classList.add('show', 'active'); } // Update active state on nav links tabLinks.forEach(link => link.classList.remove('active')); this.classList.add('active'); }); }); });