Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ 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'
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'

Expand All @@ -30,6 +31,14 @@ export default function WithdrawBankPage() {
const router = useRouter()
const [isLoading, setIsLoading] = useState(false)
const [view, setView] = useState<View>('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) {
Expand Down Expand Up @@ -226,7 +235,7 @@ export default function WithdrawBankPage() {
<PaymentInfoRow label={'Routing Number'} value={getBicAndRoutingNumber()} />
</>
)}
<ExchangeRate accountType={bankAccount.type} />
<ExchangeRate accountType={bankAccount.type} nonEuroCurrency={nonEuroCurrency} />
<PaymentInfoRow hideBottomBorder label="Fee" value={`$ 0.00`} />
</Card>
{error.showError ? (
Expand Down
2 changes: 1 addition & 1 deletion src/components/Common/SavedAccountsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
36 changes: 31 additions & 5 deletions src/components/ExchangeRate/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
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<IExchangeRate, 'enabled'> {
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'

if (accountType === AccountType.US) {
return <PaymentInfoRow loading={isFetchingRate} label="Exchange Rate" value={`1 USD`} />
}

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 (
<PaymentInfoRow
loading={isFetchingRate}
loading={isLoadingRate}
label="Exchange Rate"
moreInfoText={`Exchange rates apply when converting to ${toCurrency}`}
moreInfoText={moreInfoText}
value={displayValue}
/>
)
Expand Down
39 changes: 26 additions & 13 deletions src/constants/countryCurrencyMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,43 @@ export interface CountryCurrencyMapping {
country: string
flagCode: string
comingSoon?: boolean
path?: string
}

export const countryCurrencyMappings: CountryCurrencyMapping[] = [
// SEPA Countries (Eurozone)
{ 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 },
Expand Down
3 changes: 3 additions & 0 deletions src/hooks/useExchangeRate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface UseExchangeRateProps {
sourceCurrency: string
destinationCurrency: string
initialSourceAmount?: number
enabled?: boolean
}

interface UseExchangeRateReturn {
Expand All @@ -26,6 +27,7 @@ export function useExchangeRate({
sourceCurrency,
destinationCurrency,
initialSourceAmount = 10,
enabled = true,
}: UseExchangeRateProps): UseExchangeRateReturn {
// State
const [sourceAmount, setSourceAmount] = useState<InputValue>(initialSourceAmount)
Expand Down Expand Up @@ -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
Expand Down
12 changes: 7 additions & 5 deletions src/hooks/useGetExchangeRate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<string | null>(null)
const [isFetchingRate, setIsFetchingRate] = useState(true)
const [isFetchingRate, setIsFetchingRate] = useState(enabled)

useEffect(() => {
const fetchExchangeRate = async () => {
Expand Down Expand Up @@ -45,9 +46,10 @@ export default function useGetExchangeRate({ accountType }: IExchangeRate) {
setIsFetchingRate(false)
}
}

fetchExchangeRate()
}, [accountType])
if (enabled) {
fetchExchangeRate()
}
}, [accountType, enabled])

return { exchangeRate, isFetchingRate }
}
Loading