diff --git a/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx b/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx index 6054a03dd..0c452f09c 100644 --- a/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx +++ b/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx @@ -12,7 +12,7 @@ import { useWithdrawFlow } from '@/context/WithdrawFlowContext' import { useWallet } from '@/hooks/wallet/useWallet' import { AccountType, Account } from '@/interfaces' import { formatIban, shortenAddressLong, isTxReverted } from '@/utils/general.utils' -import { useRouter } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { useEffect, useState } from 'react' import DirectSuccessView from '@/components/Payment/Views/Status.payment.view' import { ErrorHandler, getBridgeChainName } from '@/utils' @@ -20,6 +20,7 @@ import { getOfframpCurrencyConfig } from '@/utils/bridge.utils' import { createOfframp, confirmOfframp } from '@/app/actions/offramp' import { useAuth } from '@/context/authContext' import ExchangeRate from '@/components/ExchangeRate' +import countryCurrencyMappings from '@/constants/countryCurrencyMapping' type View = 'INITIAL' | 'SUCCESS' @@ -30,6 +31,14 @@ export default function WithdrawBankPage() { const router = useRouter() const [isLoading, setIsLoading] = useState(false) const [view, setView] = useState('INITIAL') + const params = useParams() + const country = params.country as string + + const nonEuroCurrency = countryCurrencyMappings.find( + (currency) => + country.toLowerCase() === currency.country.toLowerCase() || + currency.path?.toLowerCase() === country.toLowerCase() + )?.currencyCode useEffect(() => { if (!bankAccount) { @@ -226,7 +235,7 @@ export default function WithdrawBankPage() { )} - + {error.showError ? ( diff --git a/src/components/Common/SavedAccountsView.tsx b/src/components/Common/SavedAccountsView.tsx index fca18a728..876172ada 100644 --- a/src/components/Common/SavedAccountsView.tsx +++ b/src/components/Common/SavedAccountsView.tsx @@ -83,7 +83,7 @@ export function SavedAccountsMapping({ countryInfo = ALL_METHODS_DATA.find((c) => c.id === 'US') } else { countryInfo = details.countryName - ? ALL_METHODS_DATA.find((c) => c.title.toLowerCase() === details.countryName?.toLowerCase()) + ? ALL_METHODS_DATA.find((c) => c.path.toLowerCase() === details.countryName?.toLowerCase()) : ALL_METHODS_DATA.find((c) => c.id === threeLetterCountryCode) } diff --git a/src/components/ExchangeRate/index.tsx b/src/components/ExchangeRate/index.tsx index 6dc578008..6759a1704 100644 --- a/src/components/ExchangeRate/index.tsx +++ b/src/components/ExchangeRate/index.tsx @@ -1,9 +1,20 @@ import { AccountType } from '@/interfaces' import { PaymentInfoRow } from '@/components/Payment/PaymentInfoRow' import useGetExchangeRate, { IExchangeRate } from '@/hooks/useGetExchangeRate' +import { useExchangeRate } from '@/hooks/useExchangeRate' -const ExchangeRate = ({ accountType }: IExchangeRate) => { - const { exchangeRate, isFetchingRate } = useGetExchangeRate({ accountType }) +interface IExchangeRateProps extends Omit { + nonEuroCurrency?: string +} + +const ExchangeRate = ({ accountType, nonEuroCurrency }: IExchangeRateProps) => { + const { exchangeRate, isFetchingRate } = useGetExchangeRate({ accountType, enabled: !nonEuroCurrency }) + const { exchangeRate: nonEruoExchangeRate, isLoading } = useExchangeRate({ + sourceCurrency: 'USD', + destinationCurrency: nonEuroCurrency || 'EUR', + initialSourceAmount: 1, + enabled: !!nonEuroCurrency, + }) const toCurrency = accountType === AccountType.IBAN ? 'EUR' : accountType === AccountType.CLABE ? 'MXN' : 'USD' @@ -11,13 +22,28 @@ const ExchangeRate = ({ accountType }: IExchangeRate) => { return } - const displayValue = exchangeRate ? `1 USD = ${parseFloat(exchangeRate).toFixed(4)} ${toCurrency}` : '-' + let displayValue = '-' + let isLoadingRate = false + let moreInfoText = '' + + if (nonEuroCurrency) { + displayValue = nonEruoExchangeRate + ? `1 USD = ${parseFloat(nonEruoExchangeRate.toString()).toFixed(4)} ${nonEuroCurrency}` + : '-' + isLoadingRate = isLoading + moreInfoText = + "This is an approximate value. The actual amount received may vary based on your bank's exchange rate" + } else { + displayValue = exchangeRate ? `1 USD = ${parseFloat(exchangeRate).toFixed(4)} ${toCurrency}` : '-' + isLoadingRate = isFetchingRate + moreInfoText = `Exchange rates apply when converting to ${toCurrency}` + } return ( ) diff --git a/src/constants/countryCurrencyMapping.ts b/src/constants/countryCurrencyMapping.ts index 07a86b6b1..5c5e93f7a 100644 --- a/src/constants/countryCurrencyMapping.ts +++ b/src/constants/countryCurrencyMapping.ts @@ -4,6 +4,7 @@ export interface CountryCurrencyMapping { country: string flagCode: string comingSoon?: boolean + path?: string } export const countryCurrencyMappings: CountryCurrencyMapping[] = [ @@ -11,23 +12,35 @@ export const countryCurrencyMappings: CountryCurrencyMapping[] = [ { currencyCode: 'EUR', currencyName: 'Euro', country: 'Eurozone', flagCode: 'eu' }, // Non-Eurozone SEPA Countries - { currencyCode: 'BGN', currencyName: 'Bulgarian Lev', country: 'Bulgaria', flagCode: 'bg' }, - { currencyCode: 'CZK', currencyName: 'Czech Koruna', country: 'Czech Republic', flagCode: 'cz' }, - { currencyCode: 'DKK', currencyName: 'Danish Krone', country: 'Denmark', flagCode: 'dk' }, - { currencyCode: 'HUF', currencyName: 'Hungarian Forint', country: 'Hungary', flagCode: 'hu' }, - { currencyCode: 'ISK', currencyName: 'Icelandic Krona', country: 'Iceland', flagCode: 'is' }, - { currencyCode: 'NOK', currencyName: 'Norwegian Krone', country: 'Norway', flagCode: 'no' }, - { currencyCode: 'PLN', currencyName: 'Polish Zloty', country: 'Poland', flagCode: 'pl' }, - { currencyCode: 'RON', currencyName: 'Romanian Leu', country: 'Romania', flagCode: 'ro' }, - { currencyCode: 'SEK', currencyName: 'Swedish Krona', country: 'Sweden', flagCode: 'se' }, - { currencyCode: 'CHF', currencyName: 'Swiss Franc', country: 'Switzerland', flagCode: 'ch' }, - { currencyCode: 'GBP', currencyName: 'British Pound Sterling', country: 'United Kingdom', flagCode: 'gb' }, + { currencyCode: 'BGN', currencyName: 'Bulgarian Lev', country: 'Bulgaria', flagCode: 'bg', path: 'bulgaria' }, + { + currencyCode: 'CZK', + currencyName: 'Czech Koruna', + country: 'Czech Republic', + flagCode: 'cz', + path: 'czech-republic', + }, + { currencyCode: 'DKK', currencyName: 'Danish Krone', country: 'Denmark', flagCode: 'dk', path: 'denmark' }, + { currencyCode: 'HUF', currencyName: 'Hungarian Forint', country: 'Hungary', flagCode: 'hu', path: 'hungary' }, + { currencyCode: 'ISK', currencyName: 'Icelandic Krona', country: 'Iceland', flagCode: 'is', path: 'iceland' }, + { currencyCode: 'NOK', currencyName: 'Norwegian Krone', country: 'Norway', flagCode: 'no', path: 'norway' }, + { currencyCode: 'PLN', currencyName: 'Polish Zloty', country: 'Poland', flagCode: 'pl', path: 'poland' }, + { currencyCode: 'RON', currencyName: 'Romanian Leu', country: 'Romania', flagCode: 'ro', path: 'romania' }, + { currencyCode: 'SEK', currencyName: 'Swedish Krona', country: 'Sweden', flagCode: 'se', path: 'sweden' }, + { currencyCode: 'CHF', currencyName: 'Swiss Franc', country: 'Switzerland', flagCode: 'ch', path: 'switzerland' }, + { + currencyCode: 'GBP', + currencyName: 'British Pound Sterling', + country: 'United Kingdom', + flagCode: 'gb', + path: 'united-kingdom', + }, // USA - { currencyCode: 'USD', currencyName: 'US Dollar', country: 'United States', flagCode: 'us' }, + { currencyCode: 'USD', currencyName: 'US Dollar', country: 'United States', flagCode: 'us', path: 'usa' }, // Mexico - { currencyCode: 'MXN', currencyName: 'Mexican Peso', country: 'Mexico', flagCode: 'mx' }, + { currencyCode: 'MXN', currencyName: 'Mexican Peso', country: 'Mexico', flagCode: 'mx', path: 'mexico' }, // Coming Soon { currencyCode: 'BRL', currencyName: 'Brazilian Real', country: 'Brazil', flagCode: 'br', comingSoon: true }, diff --git a/src/hooks/useExchangeRate.ts b/src/hooks/useExchangeRate.ts index bc3a960ee..c5acba263 100644 --- a/src/hooks/useExchangeRate.ts +++ b/src/hooks/useExchangeRate.ts @@ -8,6 +8,7 @@ interface UseExchangeRateProps { sourceCurrency: string destinationCurrency: string initialSourceAmount?: number + enabled?: boolean } interface UseExchangeRateReturn { @@ -26,6 +27,7 @@ export function useExchangeRate({ sourceCurrency, destinationCurrency, initialSourceAmount = 10, + enabled = true, }: UseExchangeRateProps): UseExchangeRateReturn { // State const [sourceAmount, setSourceAmount] = useState(initialSourceAmount) @@ -89,6 +91,7 @@ export function useExchangeRate({ staleTime: 2 * 60 * 1000, // 2 minutes gcTime: 10 * 60 * 1000, // garbage collect after 10 minutes refetchOnWindowFocus: false, + enabled: enabled && !!sourceCurrency && !!destinationCurrency, }) const exchangeRate = rateData?.rate ?? 0 diff --git a/src/hooks/useGetExchangeRate.tsx b/src/hooks/useGetExchangeRate.tsx index 370b8a86a..c95c0db30 100644 --- a/src/hooks/useGetExchangeRate.tsx +++ b/src/hooks/useGetExchangeRate.tsx @@ -4,15 +4,16 @@ import { useEffect, useState } from 'react' export interface IExchangeRate { accountType: AccountType + enabled?: boolean } /** * Used to get exchange rate for a given account type * @returns {string, boolean} The exchange rate for the given account type and a boolean indicating if the rate is being fetched */ -export default function useGetExchangeRate({ accountType }: IExchangeRate) { +export default function useGetExchangeRate({ accountType, enabled = true }: IExchangeRate) { const [exchangeRate, setExchangeRate] = useState(null) - const [isFetchingRate, setIsFetchingRate] = useState(true) + const [isFetchingRate, setIsFetchingRate] = useState(enabled) useEffect(() => { const fetchExchangeRate = async () => { @@ -45,9 +46,10 @@ export default function useGetExchangeRate({ accountType }: IExchangeRate) { setIsFetchingRate(false) } } - - fetchExchangeRate() - }, [accountType]) + if (enabled) { + fetchExchangeRate() + } + }, [accountType, enabled]) return { exchangeRate, isFetchingRate } }