diff --git a/basicswap/static/js/offerstable.js b/basicswap/static/js/offerstable.js index ccb62fc..c48eb32 100644 --- a/basicswap/static/js/offerstable.js +++ b/basicswap/static/js/offerstable.js @@ -268,7 +268,7 @@ function getTimeUntilNextExpiration() { return timeUntilExpiration > 0 && timeUntilExpiration < earliest ? timeUntilExpiration : earliest; }, Infinity); - return nextExpiration === Infinity ? 300 : Math.max(MIN_REFRESH_INTERVAL, Math.min(nextExpiration, 300)); + return Math.max(MIN_REFRESH_INTERVAL, Math.min(nextExpiration, 300)); } function getNoOffersMessage() { @@ -393,30 +393,34 @@ window.tableRateModule = { } }; -function updateProfitLoss(row, fromCoin, toCoin, fromAmount, toAmount) { +function updateProfitLoss(row, fromCoin, toCoin, fromAmount, toAmount, isOwnOffer) { const profitLossElement = row.querySelector('.profit-loss'); if (!profitLossElement) { console.warn('Profit loss element not found in row'); return; } - calculateProfitLoss(fromCoin, toCoin, fromAmount, toAmount) - .then(profitLossPercentage => { - if (profitLossPercentage === null) { + calculateProfitLoss(fromCoin, toCoin, fromAmount, toAmount, isOwnOffer) + .then(percentDiff => { + if (percentDiff === null) { profitLossElement.textContent = 'N/A'; profitLossElement.className = 'profit-loss text-lg font-bold text-gray-500'; console.log(`Unable to calculate profit/loss for ${fromCoin} to ${toCoin}`); return; } - const colorClass = getProfitColorClass(profitLossPercentage); - profitLossElement.textContent = `${profitLossPercentage > 0 ? '+' : ''}${profitLossPercentage}%`; + const formattedPercentDiff = percentDiff.toFixed(2); + const percentDiffDisplay = formattedPercentDiff === "0.00" ? "0.00" : + (percentDiff > 0 ? `+${formattedPercentDiff}` : formattedPercentDiff); + + const colorClass = getProfitColorClass(percentDiff); + profitLossElement.textContent = `${percentDiffDisplay}%`; profitLossElement.className = `profit-loss text-lg font-bold ${colorClass}`; const tooltipId = `percentage-tooltip-${row.getAttribute('data-offer-id')}`; const tooltipElement = document.getElementById(tooltipId); if (tooltipElement) { - const tooltipContent = createTooltipContent(isSentOffers, fromCoin, toCoin, fromAmount, toAmount); + const tooltipContent = createTooltipContent(isOwnOffer, fromCoin, toCoin, fromAmount, toAmount); tooltipElement.innerHTML = `
Time Indicator Colors:
++ + Green: More than 30 minutes left +
++ + Blue: Between 5 and 30 minutes left +
++ + Grey: Less than 5 minutes left or expired +
+Unable to calculate profit/loss
+Invalid coin data.
`; + } + + // Ensure fromAmount and toAmount are numbers + fromAmount = parseFloat(fromAmount) || 0; + toAmount = parseFloat(toAmount) || 0; + const fromSymbol = coinNameToSymbol[coinFrom] || coinFrom.toLowerCase(); const toSymbol = coinNameToSymbol[coinTo] || coinTo.toLowerCase(); const fromPriceUSD = latestPrices[fromSymbol]?.usd; @@ -1213,51 +1317,55 @@ function createTooltipContent(isSentOffers, coinFrom, coinTo, fromAmount, toAmou const fromValueUSD = fromAmount * fromPriceUSD; const toValueUSD = toAmount * toPriceUSD; const profitUSD = toValueUSD - fromValueUSD; - let profitPercentage; - if (isSentOffers) { - // Sent Offer Page - profitPercentage = ((toValueUSD / fromValueUSD) - 1) * 100; + const marketRate = fromPriceUSD / toPriceUSD; + const offerRate = toAmount / fromAmount; + let percentDiff; + + if (isSentOffers || isOwnOffer) { + percentDiff = ((toValueUSD / fromValueUSD) - 1) * 100; } else { - // Offer Page - profitPercentage = ((fromValueUSD / toValueUSD) - 1) * 100; + percentDiff = ((fromValueUSD / toValueUSD) - 1) * 100; } - const profitLabel = isSentOffers ? "Profit" : "Savings"; - const actionLabel = isSentOffers ? "selling" : "buying"; - const directionLabel = isSentOffers ? "receiving" : "paying"; + const formattedPercentDiff = percentDiff.toFixed(2); + const percentDiffDisplay = formattedPercentDiff === "0.00" ? "0.00" : + (percentDiff > 0 ? `+${formattedPercentDiff}` : formattedPercentDiff); + + const profitLabel = (isSentOffers || isOwnOffer) ? "Profit" : "Savings"; + const actionLabel = (isSentOffers || isOwnOffer) ? "selling" : "buying"; + const directionLabel = (isSentOffers || isOwnOffer) ? "receiving" : "paying"; return `Profit/Loss Calculation:
-You are ${actionLabel} ${fromAmount} ${coinFrom} (${fromValueUSD.toFixed(2)} USD)
and ${directionLabel} ${toAmount} ${coinTo} (${toValueUSD.toFixed(2)} USD).
Percentage: ${profitPercentage.toFixed(2)}%
-USD ${profitLabel}: ${profitUSD > 0 ? '+' : ''}${profitUSD.toFixed(2)} USD
+You are ${actionLabel} ${fromAmount.toFixed(8)} ${coinFrom} ($${fromValueUSD.toFixed(2)} USD)
and ${directionLabel} ${toAmount.toFixed(8)} ${coinTo} ($${toValueUSD.toFixed(2)} USD).
Percentage difference: ${percentDiffDisplay}%
+USD ${profitLabel}: ${profitUSD > 0 ? '+' : ''}$${profitUSD.toFixed(2)} USD
Calculation:
-Percentage = ${isSentOffers ? +
Percentage = ${(isSentOffers || isOwnOffer) ? "((To Amount in USD / From Amount in USD) - 1) * 100" : "((From Amount in USD / To Amount in USD) - 1) * 100"}
-USD ${profitLabel} = ${isSentOffers ? - "To Amount in USD - From Amount in USD" : - "From Amount in USD - To Amount in USD"}
+USD ${profitLabel} = To Amount in USD - From Amount in USD
Interpretation:
- ${isSentOffers ? ` -Positive percentage: You're making a profit
-Negative percentage: You're taking a loss
+ ${(isSentOffers || isOwnOffer) ? ` +Positive percentage: You're selling above market rate (profitable)
+Negative percentage: You're selling below market rate (loss)
` : ` -Positive percentage: You're saving money compared to market rates
-Negative percentage: You're paying more than current market rates
+Positive percentage: You're buying below market rate (savings)
+Negative percentage: You're buying above market rate (premium)
`} -Note: ${isSentOffers ?
- "As a seller, a positive percentage means you're selling
for more than the current market value." :
- "As a buyer, a positive percentage indicates potential savings compared to current market rates."}
Note: ${(isSentOffers || isOwnOffer) ?
+ "As a seller, a positive percentage means
you're selling for more than the current market value." :
+ "As a buyer, a positive percentage indicates potential savings compared to current market rates."}
Market Rate: 1 ${coinFrom} = ${marketRate.toFixed(8)} ${coinTo}
+Offer Rate: 1 ${coinFrom} = ${offerRate.toFixed(8)} ${coinTo}
`; } - -function createCombinedRateTooltip(offer, coinFrom, coinTo) { +function createCombinedRateTooltip(offer, coinFrom, coinTo, isSentOffers, treatAsSentOffer) { const rate = parseFloat(offer.rate); const inverseRate = 1 / rate; - const fromSymbol = coinNameToSymbol[coinFrom] || coinFrom.toLowerCase(); - const toSymbol = coinNameToSymbol[coinTo] || coinTo.toLowerCase(); + const fromSymbol = getCoinSymbolLowercase(coinFrom); + const toSymbol = getCoinSymbolLowercase(coinTo); const fromPriceUSD = latestPrices[fromSymbol]?.usd || 0; const toPriceUSD = latestPrices[toSymbol]?.usd || 0; @@ -1266,13 +1374,16 @@ function createCombinedRateTooltip(offer, coinFrom, coinTo) { const marketRate = fromPriceUSD / toPriceUSD; const percentDiff = ((rate - marketRate) / marketRate) * 100; - const aboveOrBelow = percentDiff > 0 ? "above" : "below"; + const formattedPercentDiff = percentDiff.toFixed(2); + const percentDiffDisplay = formattedPercentDiff === "0.00" ? "0.00" : + (percentDiff > 0 ? `+${formattedPercentDiff}` : formattedPercentDiff); + const aboveOrBelow = percentDiff > 0 ? "above" : percentDiff < 0 ? "below" : "at"; - const action = isSentOffers ? "selling" : "buying"; + const action = isSentOffers || treatAsSentOffer ? "selling" : "buying"; return `Exchange Rate Explanation:
-This offer is ${action} ${coinFrom} for ${coinTo}
at a rate that is ${Math.abs(percentDiff).toFixed(2)}% ${aboveOrBelow} market price.
This offer is ${action} ${coinFrom} for ${coinTo}
at a rate that is ${percentDiffDisplay}% ${aboveOrBelow} market price.
Exchange Rates:
1 ${coinFrom} = ${rate.toFixed(8)} ${coinTo}
1 ${coinTo} = ${inverseRate.toFixed(8)} ${coinFrom}
@@ -1333,15 +1444,18 @@ function updateNextRefreshTime() { const minutes = Math.floor(nextRefreshCountdown / 60); const seconds = nextRefreshCountdown % 60; - nextRefreshTimeSpan.textContent = `${minutes}m ${seconds}s`; + nextRefreshTimeSpan.textContent = `${minutes}m ${seconds.toString().padStart(2, '0')}s`; // console.log(`Next refresh in: ${minutes}m ${seconds}s`); } function updateRowTimes() { const currentTime = Math.floor(Date.now() / 1000); - jsonData.forEach(offer => { - const row = document.querySelector(`[data-offer-id="${offer.offer_id}"]`); - if (!row) return; + const rows = document.querySelectorAll('[data-offer-id]'); + + rows.forEach(row => { + const offerId = row.getAttribute('data-offer-id'); + const offer = jsonData.find(o => o.offer_id === offerId); + if (!offer) return; const timeColumn = row.querySelector('td:first-child'); if (!timeColumn) return; @@ -1358,22 +1472,22 @@ function updateRowTimes() { const textContainer = timeColumn.querySelector('.xl\\:block'); if (textContainer) { - textContainer.innerHTML = ` -© 2024~ (BSX) BasicSwap
BSX: v{{ version }}
-GUI: v3.0.0
+GUI: v3.1.0
Made with
{{ love_svg | safe }}