From 17f22c688071327608caa5be3001fa82543ebfe2 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Wed, 4 Jun 2025 15:10:30 +0200 Subject: [PATCH 1/3] Add net exchange rate calculation and update display in RampFeeCollapse --- .../src/components/RampFeeCollapse/index.tsx | 61 ++++++++++++++++--- frontend/src/translations/en.json | 4 ++ frontend/src/translations/pt.json | 4 ++ 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/RampFeeCollapse/index.tsx b/frontend/src/components/RampFeeCollapse/index.tsx index ab1c5a9fe..77d7602e1 100644 --- a/frontend/src/components/RampFeeCollapse/index.tsx +++ b/frontend/src/components/RampFeeCollapse/index.tsx @@ -4,7 +4,8 @@ import { useQuote } from '../../stores/ramp/useQuoteStore'; import { useFiatToken, useOnChainToken } from '../../stores/ramp/useRampFormStore'; import { useRampDirection } from '../../stores/rampDirectionStore'; import { RampDirection } from '../RampToggle'; -import { ArrowDownIcon, InformationCircleIcon } from '@heroicons/react/20/solid'; +import { InformationCircleIcon } from '@heroicons/react/20/solid'; +import { QuoteEndpoints } from 'shared'; interface FeeItem { label: string; @@ -12,6 +13,33 @@ interface FeeItem { value: string; } +// This function calculates the interbank exchange rate based on the quote response, neglecting any fees. +function calculateInterbankExchangeRate( + rampType: string, + inputAmountString: Big.BigSource, + outputAmountString: Big.BigSource, + fee: QuoteEndpoints.FeeStructure, +) { + const inputAmount = Big(inputAmountString); + const outputAmount = Big(outputAmountString); + + if (rampType === 'on') { + const inputAmountWithoutFees = inputAmount.minus(fee.total); + return inputAmountWithoutFees.gt(0) ? outputAmount.div(inputAmountWithoutFees).toNumber() : 0; + } else { + const outputAmountWithoutFees = outputAmount.plus(fee.total); + return inputAmount.gt(0) ? outputAmountWithoutFees.div(inputAmount).toNumber() : 0; + } +} + +// Calculate all-in exchange rate +function calculateNetExchangeRate(inputAmountString: Big.BigSource, outputAmountString: Big.BigSource) { + const inputAmount = Big(inputAmountString); + const outputAmount = Big(outputAmountString); + + return inputAmount.gt(0) ? outputAmount.div(inputAmount).toNumber() : 0; +} + export function RampFeeCollapse() { const { t } = useTranslation(); @@ -24,21 +52,23 @@ export function RampFeeCollapse() { const quote = availableQuote ? availableQuote : { + rampType: 'on', inputAmount: 0, outputAmount: 0, inputCurrency: rampDirection === RampDirection.ONRAMP ? fiatToken : onChainToken, outputCurrency: rampDirection === RampDirection.ONRAMP ? onChainToken : fiatToken, - fee: { total: 0, network: 0, vortex: 0, anchor: 0, partnerMarkup: 0, currency: fiatToken }, + fee: { total: '0', network: '0', vortex: '0', anchor: '0', partnerMarkup: '0', currency: fiatToken }, }; - // Calculate exchange rate - const inputAmount = Big(quote.inputAmount); - const outputAmount = Big(quote.outputAmount); const inputCurrency = quote.inputCurrency.toUpperCase(); const outputCurrency = quote.outputCurrency.toUpperCase(); - - // Calculate exchange rate (how much outputCurrency you get for 1 inputCurrency) - const exchangeRate = inputAmount.gt(0) ? outputAmount.div(inputAmount).toNumber() : 0; + const interbankExchangeRate = calculateInterbankExchangeRate( + quote.rampType, + quote.inputAmount, + quote.outputAmount, + quote.fee, + ); + const netExchangeRate = calculateNetExchangeRate(quote.inputAmount, quote.outputAmount); // Generate fee items for display const feeItems: FeeItem[] = []; @@ -64,7 +94,7 @@ export function RampFeeCollapse() { return (
- {`1 ${inputCurrency} ≈ ${exchangeRate.toFixed(4)} ${outputCurrency}`} + {`1 ${inputCurrency} ≈ ${interbankExchangeRate.toFixed(4)} ${outputCurrency}`}
@@ -96,6 +126,19 @@ export function RampFeeCollapse() {
+
+
+ + {t('components.feeCollapse.netRate.label')} + +
+
+ {`1 ${inputCurrency} ≈ ${netExchangeRate.toFixed(4)} ${outputCurrency}`} +
+
diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index 5cdad06d0..d9f42292d 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -328,6 +328,10 @@ "tooltip": "The cost to transfer funds to your wallet, which varies with selected network and network congestion." }, "totalFee": "Total Fee", + "netRate": { + "label": "Effective Rate", + "tooltip": "This is the exchange rate you receive after all processing and network fees have been deducted." + }, "finalAmount": "Final Amount" }, "transactionStatusBanner": { diff --git a/frontend/src/translations/pt.json b/frontend/src/translations/pt.json index 28eaa805f..25bbd7cfb 100644 --- a/frontend/src/translations/pt.json +++ b/frontend/src/translations/pt.json @@ -326,6 +326,10 @@ "label": "Taxa de rede", "tooltip": "O custo para transferir fundos para sua carteira, que varia conforme a rede selecionada e a congestão da rede." }, + "netRate": { + "label": "Taxa Efetiva", + "tooltip": "Esta é a taxa de câmbio que você recebe após a dedução de todas as taxas de processamento e de rede." + }, "totalFee": "Taxa total", "finalAmount": "Valor final" }, From eb1d38696148893f433a0739f25df56538e1a5f7 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Wed, 4 Jun 2025 15:16:56 +0200 Subject: [PATCH 2/3] Refactor and reword --- frontend/src/components/RampFeeCollapse/index.tsx | 11 +++++++---- frontend/src/translations/pt.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/RampFeeCollapse/index.tsx b/frontend/src/components/RampFeeCollapse/index.tsx index 77d7602e1..0f5b980c5 100644 --- a/frontend/src/components/RampFeeCollapse/index.tsx +++ b/frontend/src/components/RampFeeCollapse/index.tsx @@ -23,13 +23,16 @@ function calculateInterbankExchangeRate( const inputAmount = Big(inputAmountString); const outputAmount = Big(outputAmountString); + let effectiveInputAmount = inputAmount; + let effectiveOutputAmount = outputAmount; + if (rampType === 'on') { - const inputAmountWithoutFees = inputAmount.minus(fee.total); - return inputAmountWithoutFees.gt(0) ? outputAmount.div(inputAmountWithoutFees).toNumber() : 0; + effectiveInputAmount = inputAmount.minus(fee.total); } else { - const outputAmountWithoutFees = outputAmount.plus(fee.total); - return inputAmount.gt(0) ? outputAmountWithoutFees.div(inputAmount).toNumber() : 0; + effectiveOutputAmount = outputAmount.plus(fee.total); } + + return effectiveInputAmount.gt(0) ? effectiveOutputAmount.div(effectiveInputAmount).toNumber() : 0; } // Calculate all-in exchange rate diff --git a/frontend/src/translations/pt.json b/frontend/src/translations/pt.json index 25bbd7cfb..dc7530815 100644 --- a/frontend/src/translations/pt.json +++ b/frontend/src/translations/pt.json @@ -327,7 +327,7 @@ "tooltip": "O custo para transferir fundos para sua carteira, que varia conforme a rede selecionada e a congestão da rede." }, "netRate": { - "label": "Taxa Efetiva", + "label": "Câmbio Efetiva", "tooltip": "Esta é a taxa de câmbio que você recebe após a dedução de todas as taxas de processamento e de rede." }, "totalFee": "Taxa total", From 38661541d74f6f917d0a3b57f75523f09c81ab2f Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Wed, 4 Jun 2025 15:20:02 +0200 Subject: [PATCH 3/3] Refactor --- frontend/src/components/RampFeeCollapse/index.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/RampFeeCollapse/index.tsx b/frontend/src/components/RampFeeCollapse/index.tsx index 0f5b980c5..9fbd6005b 100644 --- a/frontend/src/components/RampFeeCollapse/index.tsx +++ b/frontend/src/components/RampFeeCollapse/index.tsx @@ -43,6 +43,11 @@ function calculateNetExchangeRate(inputAmountString: Big.BigSource, outputAmount return inputAmount.gt(0) ? outputAmount.div(inputAmount).toNumber() : 0; } +// Helper function to format exchange rate strings +function formatExchangeRateString(rate: number, input: string, output: string) { + return `1 ${input} ≈ ${rate.toFixed(4)} ${output}`; +} + export function RampFeeCollapse() { const { t } = useTranslation(); @@ -97,7 +102,7 @@ export function RampFeeCollapse() { return (
- {`1 ${inputCurrency} ≈ ${interbankExchangeRate.toFixed(4)} ${outputCurrency}`} + {formatExchangeRateString(interbankExchangeRate, inputCurrency, outputCurrency)}
@@ -139,7 +144,7 @@ export function RampFeeCollapse() {
- {`1 ${inputCurrency} ≈ ${netExchangeRate.toFixed(4)} ${outputCurrency}`} + {formatExchangeRateString(netExchangeRate, inputCurrency, outputCurrency)}