diff --git a/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx b/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx index 6c79fe04b..85218f9b3 100644 --- a/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx +++ b/src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx @@ -1,7 +1,7 @@ 'use client' import { Button } from '@/components/0_Bruddle' -import { countryCodeMap } from '@/components/AddMoney/consts' +import { ALL_COUNTRIES_ALPHA3_TO_ALPHA2 } from '@/components/AddMoney/consts' import Card from '@/components/Global/Card' import ErrorAlert from '@/components/Global/ErrorAlert' import NavHeader from '@/components/Global/NavHeader' @@ -183,7 +183,8 @@ export default function WithdrawBankPage() { const countryCodeForFlag = () => { if (!bankAccount?.details?.countryCode) return '' - const code = countryCodeMap[bankAccount.details.countryCode ?? ''] ?? bankAccount.details.countryCode + const code = + ALL_COUNTRIES_ALPHA3_TO_ALPHA2[bankAccount.details.countryCode ?? ''] ?? bankAccount.details.countryCode return code.toLowerCase() } diff --git a/src/app/(mobile-ui)/withdraw/manteca/page.tsx b/src/app/(mobile-ui)/withdraw/manteca/page.tsx index 45179e276..ef7512284 100644 --- a/src/app/(mobile-ui)/withdraw/manteca/page.tsx +++ b/src/app/(mobile-ui)/withdraw/manteca/page.tsx @@ -42,7 +42,9 @@ export default function MantecaWithdrawFlow() { const [usdAmount, setUsdAmount] = useState(undefined) const [step, setStep] = useState('amountInput') const [balanceErrorMessage, setBalanceErrorMessage] = useState(null) - const [destinationAddress, setDestinationAddress] = useState('') + const searchParams = useSearchParams() + const paramAddress = searchParams.get('destination') + const [destinationAddress, setDestinationAddress] = useState(paramAddress ?? '') const [selectedBank, setSelectedBank] = useState(null) const [accountType, setAccountType] = useState(null) const [errorMessage, setErrorMessage] = useState(null) @@ -50,7 +52,6 @@ export default function MantecaWithdrawFlow() { const [isDestinationAddressValid, setIsDestinationAddressValid] = useState(false) const [isDestinationAddressChanging, setIsDestinationAddressChanging] = useState(false) const router = useRouter() - const searchParams = useSearchParams() const { sendMoney, balance } = useWallet() const { isLoading, loadingState, setLoadingState } = useContext(loadingStateContext) const { user, fetchUser } = useAuth() @@ -223,7 +224,7 @@ export default function MantecaWithdrawFlow() { setAmount(undefined) setCurrencyAmount(undefined) setUsdAmount(undefined) - setDestinationAddress('') + setDestinationAddress(paramAddress ?? '') setSelectedBank(null) setAccountType(null) setErrorMessage(null) diff --git a/src/components/AddMoney/components/AddMoneyBankDetails.tsx b/src/components/AddMoney/components/AddMoneyBankDetails.tsx index 1472e6d40..3677f3236 100644 --- a/src/components/AddMoney/components/AddMoneyBankDetails.tsx +++ b/src/components/AddMoney/components/AddMoneyBankDetails.tsx @@ -9,7 +9,7 @@ import { PEANUT_WALLET_TOKEN_SYMBOL } from '@/constants' import { useOnrampFlow } from '@/context/OnrampFlowContext' import { useRouter, useParams } from 'next/navigation' import { useCallback, useEffect, useMemo } from 'react' -import { countryCodeMap, CountryData, countryData } from '@/components/AddMoney/consts' +import { ALL_COUNTRIES_ALPHA3_TO_ALPHA2, CountryData, countryData } from '@/components/AddMoney/consts' import { formatCurrencyAmount } from '@/utils/currency' import { formatBankAccountDisplay } from '@/utils/format.utils' import Icon from '@/components/Global/Icon' @@ -93,7 +93,7 @@ export default function AddMoneyBankDetails({ flow = 'add-money' }: IAddMoneyBan const countryCodeForFlag = useMemo(() => { const countryId = currentCountryDetails?.id || 'USA' - const countryCode = countryCodeMap[countryId] || countryId // if countryId is not in countryCodeMap, use countryId because for some countries countryId is of 2 digit and countryCodeMap is a mapping of 3 digit to 2 digit country codes + const countryCode = ALL_COUNTRIES_ALPHA3_TO_ALPHA2[countryId] || countryId // if countryId is not in countryCodeMap, use countryId because for some countries countryId is of 2 digit and countryCodeMap is a mapping of 3 digit to 2 digit country codes return countryCode?.toLowerCase() || 'us' }, [currentCountryDetails]) diff --git a/src/components/AddMoney/components/DepositMethodList.tsx b/src/components/AddMoney/components/DepositMethodList.tsx index 838085590..9cd6679f4 100644 --- a/src/components/AddMoney/components/DepositMethodList.tsx +++ b/src/components/AddMoney/components/DepositMethodList.tsx @@ -4,7 +4,7 @@ import AvatarWithBadge from '@/components/Profile/AvatarWithBadge' import { SearchResultCard } from '@/components/SearchUsers/SearchResultCard' import Image from 'next/image' import { twMerge } from 'tailwind-merge' -import { countryCodeMap } from '../consts' +import { ALL_COUNTRIES_ALPHA3_TO_ALPHA2 } from '../consts' export interface DepositMethod { type: 'crypto' | 'country' @@ -54,7 +54,8 @@ export const DepositMethodList = ({ methods, onItemClick, isAllMethodsView = fal } const threeLetterCountryCode = (method.id ?? '').toUpperCase() - const twoLetterCountryCode = countryCodeMap[threeLetterCountryCode] ?? threeLetterCountryCode + const twoLetterCountryCode = + ALL_COUNTRIES_ALPHA3_TO_ALPHA2[threeLetterCountryCode] ?? threeLetterCountryCode const countryCodeForFlag = twoLetterCountryCode.toLowerCase() ?? '' diff --git a/src/components/AddMoney/consts/index.ts b/src/components/AddMoney/consts/index.ts index 9c21e2293..afb8ebb3c 100644 --- a/src/components/AddMoney/consts/index.ts +++ b/src/components/AddMoney/consts/index.ts @@ -2484,7 +2484,7 @@ const LATAM_COUNTRY_CODES = [ // bridge EAA country codes, source: https://apidocs.bridge.xyz/docs/sepa-euro-transactions // note: this is a map of 3-letter country codes to 2-letter country codes, for flags to work, bridge expects 3 letter codes -export const countryCodeMap: { [key: string]: string } = { +export const BRIDGE_ALPHA3_TO_ALPHA2: { [key: string]: string } = { ALA: 'AX', AND: 'AD', AUT: 'AT', @@ -2528,9 +2528,20 @@ export const countryCodeMap: { [key: string]: string } = { USA: 'US', } -const enabledBankWithdrawCountries = new Set([...Object.values(countryCodeMap), 'US', 'MX', 'AR', 'BO']) +export const MANTECA_ALPHA3_TO_ALPHA2: { [key: string]: string } = { + ARG: 'AR', + BOL: 'BO', + BRA: 'BR', +} + +export const ALL_COUNTRIES_ALPHA3_TO_ALPHA2: { [key: string]: string } = { + ...BRIDGE_ALPHA3_TO_ALPHA2, + ...MANTECA_ALPHA3_TO_ALPHA2, +} + +const enabledBankWithdrawCountries = new Set([...Object.values(BRIDGE_ALPHA3_TO_ALPHA2), 'US', 'MX', 'AR', 'BO']) -const enabledBankDepositCountries = new Set([...Object.values(countryCodeMap), 'US', 'AR']) +const enabledBankDepositCountries = new Set([...Object.values(BRIDGE_ALPHA3_TO_ALPHA2), 'US', 'AR']) // Helper function to check if a country code is enabled for bank transfers // Handles both 2-letter and 3-letter country codes @@ -2542,7 +2553,7 @@ const isCountryEnabledForBankTransfer = (countryCode: string, direction: 'withdr } // Check if it's a 3-letter code that maps to an enabled 2-letter code - const mappedCode = countryCodeMap[countryCode] + const mappedCode = ALL_COUNTRIES_ALPHA3_TO_ALPHA2[countryCode] return mappedCode ? enabledCountries.has(mappedCode) : false } diff --git a/src/components/AddWithdraw/AddWithdrawRouterView.tsx b/src/components/AddWithdraw/AddWithdrawRouterView.tsx index 878848649..b0c58f7ef 100644 --- a/src/components/AddWithdraw/AddWithdrawRouterView.tsx +++ b/src/components/AddWithdraw/AddWithdrawRouterView.tsx @@ -26,6 +26,27 @@ interface AddWithdrawRouterViewProps { const MAX_RECENT_METHODS = 5 +function saveRecentMethod(method: DepositMethod) { + const newRecentMethod: RecentMethod = { + id: method.id, + type: method.type as 'crypto' | 'country', + title: method.title, + description: method.description, + iconUrl: method.iconUrl, + currency: method.currency, + path: method.path, + } + + const prefs = getUserPreferences() || {} + const currentRecentList = prefs.recentAddMethods || [] + + const filteredList = currentRecentList.filter((m) => m.id !== newRecentMethod.id) + + const updatedRecentList = [newRecentMethod, ...filteredList].slice(0, MAX_RECENT_METHODS) + + updateUserPreferences({ ...prefs, recentAddMethods: updatedRecentList }) +} + export const AddWithdrawRouterView: FC = ({ flow, pageTitle, @@ -57,7 +78,10 @@ export const AddWithdrawRouterView: FC = ({ const bankAccounts = user?.accounts.filter( (acc) => - acc.type === AccountType.IBAN || acc.type === AccountType.US || acc.type === AccountType.CLABE + acc.type === AccountType.IBAN || + acc.type === AccountType.US || + acc.type === AccountType.CLABE || + acc.type === AccountType.MANTECA ) ?? [] if (bankAccounts.length > 0) { @@ -81,6 +105,10 @@ export const AddWithdrawRouterView: FC = ({ }, [flow, user, setShouldShowAllMethods]) const handleMethodSelected = (method: DepositMethod) => { + if (flow === 'add') { + saveRecentMethod(method) + } + // Handle "From Bank" specially for add flow if (flow === 'add' && method.id === 'bank-transfer-add') { setFromBankSelected(true) @@ -108,37 +136,6 @@ export const AddWithdrawRouterView: FC = ({ return } - // Original add flow logic - const newRecentMethod: RecentMethod = { - id: method.id, - type: method.type as 'crypto' | 'country', - title: method.title, - description: method.description, - iconUrl: method.iconUrl, - currency: method.currency, - path: method.path, - } - - const prefs = getUserPreferences() || {} - let currentRecentList: RecentMethod[] = [] - if (flow === 'add') { - currentRecentList = prefs.recentAddMethods || [] - } else { - currentRecentList = prefs.recentWithdrawMethods || [] - } - - const filteredList = currentRecentList.filter( - (m) => !(m.id === newRecentMethod.id && m.type === newRecentMethod.type) - ) - - const updatedRecentList = [newRecentMethod, ...filteredList].slice(0, MAX_RECENT_METHODS) - - if (flow === 'add') { - updateUserPreferences({ ...prefs, recentAddMethods: updatedRecentList }) - } else { - // for withdraw, we don't save to recents from the 'all methods' list, we show saved accounts - } - if (method.path) { router.push(method.path) } @@ -190,7 +187,13 @@ export const AddWithdrawRouterView: FC = ({ // FIXED: For withdraw flow, route to saved account path if (flow === 'withdraw') { - router.push(path) + if (account.type === AccountType.MANTECA) { + router.push( + `/withdraw/manteca?country=${account.details.countryName}&destination=${account.identifier}` + ) + } else { + router.push(path) + } return } @@ -261,13 +264,13 @@ export const AddWithdrawRouterView: FC = ({ viewMode="add-withdraw" onCountryClick={(country) => { if (flow === 'withdraw') { - // FIXED: Route directly to country page for method selection const countryPath = `${baseRoute}/${country.path}` router.push(countryPath) return } - // Original add flow + //Add + saveRecentMethod(country) const countryPath = `${baseRoute}/${country.path}` router.push(countryPath) }} diff --git a/src/components/AddWithdraw/DynamicBankAccountForm.tsx b/src/components/AddWithdraw/DynamicBankAccountForm.tsx index 89936dcd6..e5dd623c5 100644 --- a/src/components/AddWithdraw/DynamicBankAccountForm.tsx +++ b/src/components/AddWithdraw/DynamicBankAccountForm.tsx @@ -5,7 +5,7 @@ import { useAuth } from '@/context/authContext' import { Button } from '@/components/0_Bruddle/Button' import { AddBankAccountPayload, BridgeAccountOwnerType, BridgeAccountType } from '@/app/actions/types/users.types' import BaseInput from '@/components/0_Bruddle/BaseInput' -import { countryCodeMap } from '@/components/AddMoney/consts' +import { BRIDGE_ALPHA3_TO_ALPHA2, ALL_COUNTRIES_ALPHA3_TO_ALPHA2 } from '@/components/AddMoney/consts' import { useParams, useRouter } from 'next/navigation' import { validateIban, validateBic, isValidRoutingNumber } from '@/utils/bridge-accounts.utils' import ErrorAlert from '@/components/Global/ErrorAlert' @@ -20,7 +20,7 @@ import { bankFormActions } from '@/redux/slices/bank-form-slice' import { useDebounce } from '@/hooks/useDebounce' const isIBANCountry = (country: string) => { - return countryCodeMap[country.toUpperCase()] !== undefined + return BRIDGE_ALPHA3_TO_ALPHA2[country.toUpperCase()] !== undefined } export type IBankAccountDetails = { @@ -266,7 +266,7 @@ export const DynamicBankAccountForm = forwardRef<{ handleSubmit: () => void }, D ) const countryCodeForFlag = useMemo(() => { - return countryCodeMap[country.toUpperCase()] ?? country.toUpperCase() + return ALL_COUNTRIES_ALPHA3_TO_ALPHA2[country.toUpperCase()] ?? country.toUpperCase() }, [country]) return ( diff --git a/src/components/Claim/Link/views/Confirm.bank-claim.view.tsx b/src/components/Claim/Link/views/Confirm.bank-claim.view.tsx index e0df2d795..12ea4596c 100644 --- a/src/components/Claim/Link/views/Confirm.bank-claim.view.tsx +++ b/src/components/Claim/Link/views/Confirm.bank-claim.view.tsx @@ -1,7 +1,7 @@ 'use client' import { Button } from '@/components/0_Bruddle' -import { countryCodeMap } from '@/components/AddMoney/consts' +import { ALL_COUNTRIES_ALPHA3_TO_ALPHA2 } from '@/components/AddMoney/consts' import Card from '@/components/Global/Card' import ErrorAlert from '@/components/Global/ErrorAlert' import NavHeader from '@/components/Global/NavHeader' @@ -50,7 +50,7 @@ export function ConfirmBankClaimView({ }, [bankDetails]) const countryCodeForFlag = useMemo(() => { - return countryCodeMap[bankDetails?.country?.toUpperCase()] ?? bankDetails.country.toUpperCase() + return ALL_COUNTRIES_ALPHA3_TO_ALPHA2[bankDetails?.country?.toUpperCase()] ?? bankDetails.country.toUpperCase() }, [bankDetails.country]) // amount in USD from claim link data diff --git a/src/components/Common/CountryList.tsx b/src/components/Common/CountryList.tsx index 59ad55cd3..f914affa2 100644 --- a/src/components/Common/CountryList.tsx +++ b/src/components/Common/CountryList.tsx @@ -1,5 +1,11 @@ 'use client' -import { countryCodeMap, CountryData, countryData, MantecaSupportedExchanges } from '@/components/AddMoney/consts' +import { + BRIDGE_ALPHA3_TO_ALPHA2, + CountryData, + countryData, + MantecaSupportedExchanges, + ALL_COUNTRIES_ALPHA3_TO_ALPHA2, +} from '@/components/AddMoney/consts' import EmptyState from '@/components/Global/EmptyStates/EmptyState' import { SearchInput } from '@/components/SearchUsers/SearchInput' import { SearchResultCard } from '@/components/SearchUsers/SearchResultCard' @@ -49,9 +55,11 @@ export const CountryList = ({ return [...supportedCountries].sort((a, b) => { if (userGeoLocationCountryCode) { const aIsUserCountry = - countryCodeMap[a.id] === userGeoLocationCountryCode || a.id === userGeoLocationCountryCode + ALL_COUNTRIES_ALPHA3_TO_ALPHA2[a.id] === userGeoLocationCountryCode || + a.id === userGeoLocationCountryCode const bIsUserCountry = - countryCodeMap[b.id] === userGeoLocationCountryCode || b.id === userGeoLocationCountryCode + ALL_COUNTRIES_ALPHA3_TO_ALPHA2[b.id] === userGeoLocationCountryCode || + b.id === userGeoLocationCountryCode if (aIsUserCountry && !bIsUserCountry) return -1 if (!aIsUserCountry && bIsUserCountry) return 1 @@ -107,14 +115,14 @@ export const CountryList = ({ {filteredCountries.length > 0 ? ( filteredCountries.map((country, index) => { const twoLetterCountryCode = - countryCodeMap[country.id.toUpperCase()] ?? country.id.toLowerCase() + ALL_COUNTRIES_ALPHA3_TO_ALPHA2[country.id.toUpperCase()] ?? country.id.toLowerCase() const position = getCardPosition(index, filteredCountries.length) const isBridgeSupportedCountry = [ 'US', 'MX', - ...Object.keys(countryCodeMap), - ...Object.values(countryCodeMap), + ...Object.keys(BRIDGE_ALPHA3_TO_ALPHA2), + ...Object.values(BRIDGE_ALPHA3_TO_ALPHA2), ].includes(country.id) const isMantecaSupportedCountry = Object.keys(MantecaSupportedExchanges).includes( country.id diff --git a/src/components/Common/SavedAccountsView.tsx b/src/components/Common/SavedAccountsView.tsx index 600d3d340..9129416b3 100644 --- a/src/components/Common/SavedAccountsView.tsx +++ b/src/components/Common/SavedAccountsView.tsx @@ -1,5 +1,5 @@ 'use client' -import { countryData as ALL_METHODS_DATA, countryCodeMap } from '@/components/AddMoney/consts' +import { countryData as ALL_METHODS_DATA, ALL_COUNTRIES_ALPHA3_TO_ALPHA2 } from '@/components/AddMoney/consts' import { shortenStringLong, formatIban } from '@/utils/general.utils' import { AccountType, Account } from '@/interfaces' import Image from 'next/image' @@ -74,7 +74,8 @@ export function SavedAccountsMapping({ } const threeLetterCountryCode = (details.countryCode ?? '').toUpperCase() - const twoLetterCountryCode = countryCodeMap[threeLetterCountryCode] ?? threeLetterCountryCode + const twoLetterCountryCode = + ALL_COUNTRIES_ALPHA3_TO_ALPHA2[threeLetterCountryCode] ?? threeLetterCountryCode const countryCodeForFlag = twoLetterCountryCode.toLowerCase() ?? '' diff --git a/src/components/Kyc/KycStatusDrawer.tsx b/src/components/Kyc/KycStatusDrawer.tsx index bf8834563..fbd23234b 100644 --- a/src/components/Kyc/KycStatusDrawer.tsx +++ b/src/components/Kyc/KycStatusDrawer.tsx @@ -120,7 +120,7 @@ export const KycStatusDrawer = ({ isOpen, onClose, verification, bridgeKycStatus case 'processing': return ( @@ -137,7 +137,7 @@ export const KycStatusDrawer = ({ isOpen, onClose, verification, bridgeKycStatus return ( { return ( upper === 'US' || upper === 'MX' || - Object.keys(countryCodeMap).includes(upper) || - Object.values(countryCodeMap).includes(upper) + Object.keys(BRIDGE_ALPHA3_TO_ALPHA2).includes(upper) || + Object.values(BRIDGE_ALPHA3_TO_ALPHA2).includes(upper) ) } diff --git a/src/interfaces/interfaces.ts b/src/interfaces/interfaces.ts index 030da12e4..769531eb6 100644 --- a/src/interfaces/interfaces.ts +++ b/src/interfaces/interfaces.ts @@ -269,6 +269,7 @@ export enum AccountType { EVM_ADDRESS = 'evm-address', PEANUT_WALLET = 'peanut-wallet', BRIDGE = 'bridgeBankAccount', + MANTECA = 'manteca', } export interface Account { diff --git a/src/utils/withdraw.utils.ts b/src/utils/withdraw.utils.ts index 9a65ce148..4eeb67bd5 100644 --- a/src/utils/withdraw.utils.ts +++ b/src/utils/withdraw.utils.ts @@ -1,4 +1,4 @@ -import { countryData, countryCodeMap } from '@/components/AddMoney/consts' +import { countryData, ALL_COUNTRIES_ALPHA3_TO_ALPHA2 } from '@/components/AddMoney/consts' /** * Extracts the country name from an IBAN by parsing the first 2 characters (country code) @@ -136,12 +136,14 @@ export const validateMXCLabeAccount = (accountNumber: string) => { // Returns the 3-letter country code for the given country code export const getCountryCodeForWithdraw = (country: string) => { // If the input is already a 3-digit code and exists in the map, return it - if (countryCodeMap[country]) { + if (ALL_COUNTRIES_ALPHA3_TO_ALPHA2[country]) { return country } // If the input is a 2-digit code, find the corresponding 3-digit code - const threeDigitCode = Object.keys(countryCodeMap).find((key) => countryCodeMap[key] === country) + const threeDigitCode = Object.keys(ALL_COUNTRIES_ALPHA3_TO_ALPHA2).find( + (key) => ALL_COUNTRIES_ALPHA3_TO_ALPHA2[key] === country + ) return threeDigitCode || country }