diff --git a/src/app/(mobile-ui)/add-money/[country]/[regional-method]/page.tsx b/src/app/(mobile-ui)/add-money/[country]/[regional-method]/page.tsx index 61bb917b5..d7d070ebc 100644 --- a/src/app/(mobile-ui)/add-money/[country]/[regional-method]/page.tsx +++ b/src/app/(mobile-ui)/add-money/[country]/[regional-method]/page.tsx @@ -1,5 +1,5 @@ 'use client' -import MercadoPago from '@/components/AddMoney/components/RegionalMethods/MercadoPago' +import MantecaAddMoney from '@/components/AddMoney/components/MantecaAddMoney' import { CountryData, countryData } from '@/components/AddMoney/consts' import { MantecaSupportedExchanges } from '@/components/AddMoney/consts' import { useParams } from 'next/navigation' @@ -13,10 +13,9 @@ export default function AddMoneyRegionalMethodPage() { if ( MantecaSupportedExchanges[countryDetails?.id as keyof typeof MantecaSupportedExchanges] && - method === 'mercadopago' + method === 'manteca' ) { - return + return } - - return
Unsupported Method
+ return null } diff --git a/src/app/(mobile-ui)/add-money/[country]/bank/page.tsx b/src/app/(mobile-ui)/add-money/[country]/bank/page.tsx index f102d881b..655eaf931 100644 --- a/src/app/(mobile-ui)/add-money/[country]/bank/page.tsx +++ b/src/app/(mobile-ui)/add-money/[country]/bank/page.tsx @@ -24,7 +24,6 @@ import { updateUserById } from '@/app/actions/users' import AddMoneyBankDetails from '@/components/AddMoney/components/AddMoneyBankDetails' import { getCurrencyConfig, getCurrencySymbol, getMinimumAmount } from '@/utils/bridge.utils' import { OnrampConfirmationModal } from '@/components/AddMoney/components/OnrampConfirmationModal' -import MercadoPago from '@/components/AddMoney/components/RegionalMethods/MercadoPago' import { InitiateBridgeKYCModal } from '@/components/Kyc/InitiateBridgeKYCModal' type AddStep = 'inputAmount' | 'kyc' | 'loading' | 'collectUserDetails' | 'showDetails' @@ -319,11 +318,6 @@ export default function OnrampBankPage() { return } - // Show Mercado Pago flow for Argentina bank transfers - if (step === 'inputAmount' && selectedCountry.id === 'AR') { - return - } - if (step === 'inputAmount') { return (
diff --git a/src/components/AddMoney/components/InputAmountStep.tsx b/src/components/AddMoney/components/InputAmountStep.tsx index b2ffe835c..5ade987df 100644 --- a/src/components/AddMoney/components/InputAmountStep.tsx +++ b/src/components/AddMoney/components/InputAmountStep.tsx @@ -44,8 +44,6 @@ const InputAmountStep = ({ setTokenAmount(e ?? '')} - walletBalance={undefined} - hideCurrencyToggle setUsdValue={(e) => setTokenUSDAmount(e)} currency={ currencyData @@ -56,7 +54,7 @@ const InputAmountStep = ({ } : undefined } - hideBalance={true} + hideBalance />
diff --git a/src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx b/src/components/AddMoney/components/MantecaAddMoney.tsx similarity index 89% rename from src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx rename to src/components/AddMoney/components/MantecaAddMoney.tsx index 42e44eb6d..1dabbe00f 100644 --- a/src/components/AddMoney/components/RegionalMethods/MercadoPago/index.tsx +++ b/src/components/AddMoney/components/MantecaAddMoney.tsx @@ -1,10 +1,10 @@ 'use client' import { FC, useEffect, useMemo, useState } from 'react' -import MercadoPagoDepositDetails from './MercadoPagoDepositDetails' -import InputAmountStep from '../../InputAmountStep' +import MantecaDepositShareDetails from '@/components/AddMoney/components/MantecaDepositShareDetails' +import InputAmountStep from '@/components/AddMoney/components/InputAmountStep' import { useParams, useRouter } from 'next/navigation' import { CountryData, countryData } from '@/components/AddMoney/consts' -import { MantecaDepositDetails } from '@/types/manteca.types' +import { MantecaDepositResponseData } from '@/types/manteca.types' import { InitiateMantecaKYCModal } from '@/components/Kyc/InitiateMantecaKYCModal' import { useMantecaKycFlow } from '@/hooks/useMantecaKycFlow' import { useCurrency } from '@/hooks/useCurrency' @@ -12,13 +12,13 @@ import { useAuth } from '@/context/authContext' import { useWebSocket } from '@/hooks/useWebSocket' import { mantecaApi } from '@/services/manteca' -interface MercadoPagoProps { +interface MantecaAddMoneyProps { source: 'bank' | 'regionalMethod' } type stepType = 'inputAmount' | 'depositDetails' -const MercadoPago: FC = ({ source }) => { +const MantecaAddMoney: FC = ({ source }) => { const params = useParams() const router = useRouter() const [step, setStep] = useState('inputAmount') @@ -26,7 +26,7 @@ const MercadoPago: FC = ({ source }) => { const [tokenAmount, setTokenAmount] = useState('') const [tokenUSDAmount, setTokenUSDAmount] = useState('') const [error, setError] = useState(null) - const [depositDetails, setDepositDetails] = useState() + const [depositDetails, setDepositDetails] = useState() const [isKycModalOpen, setIsKycModalOpen] = useState(false) const selectedCountryPath = params.country as string @@ -97,7 +97,7 @@ const MercadoPago: FC = ({ source }) => { if (isMantecaKycRequired) { setIsKycModalOpen(true) } - }, [isMantecaKycRequired, countryData]) + }, [isMantecaKycRequired]) if (!selectedCountry) return null @@ -131,10 +131,10 @@ const MercadoPago: FC = ({ source }) => { } if (step === 'depositDetails' && depositDetails) { - return + return } return null } -export default MercadoPago +export default MantecaAddMoney diff --git a/src/components/AddMoney/components/MantecaDepositCard.tsx b/src/components/AddMoney/components/MantecaDepositCard.tsx deleted file mode 100644 index cef3af572..000000000 --- a/src/components/AddMoney/components/MantecaDepositCard.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { MERCADO_PAGO } from '@/assets' -import MantecaDetailsCard from '@/components/Global/MantecaDetailsCard' -import PeanutActionDetailsCard from '@/components/Global/PeanutActionDetailsCard' -import { PEANUT_WALLET_TOKEN_SYMBOL } from '@/constants' - -interface MantecaDepositCardProps { - countryCodeForFlag: string - currencySymbol: string - amount: string - cbu?: string - alias?: string - depositAddress?: string - pixKey?: string - isMercadoPago: boolean -} - -const MantecaDepositCard = ({ - countryCodeForFlag, - currencySymbol, - amount, - cbu, - alias, - depositAddress, - pixKey, - isMercadoPago, -}: MantecaDepositCardProps) => { - return ( -
- - -

Account details

- {(() => { - const rows = [ - ...(cbu - ? [{ key: 'cbu', label: 'CBU', value: cbu, allowCopy: true, hideBottomBorder: false }] - : []), - ...(alias ? [{ key: 'alias', label: 'Alias', value: alias, hideBottomBorder: false }] : []), - ...(depositAddress - ? [{ key: 'deposit', label: 'Deposit Address', value: depositAddress, hideBottomBorder: false }] - : []), - ...(pixKey ? [{ key: 'pix', label: 'Pix Key', value: pixKey, hideBottomBorder: false }] : []), - ] - if (rows.length) { - rows[rows.length - 1].hideBottomBorder = true - } - return - })()} -
- ) -} - -export default MantecaDepositCard diff --git a/src/components/AddMoney/components/MantecaDepositShareDetails.tsx b/src/components/AddMoney/components/MantecaDepositShareDetails.tsx new file mode 100644 index 000000000..c2be8c585 --- /dev/null +++ b/src/components/AddMoney/components/MantecaDepositShareDetails.tsx @@ -0,0 +1,132 @@ +'use client' + +import NavHeader from '@/components/Global/NavHeader' +import { useParams, useRouter } from 'next/navigation' +import React, { useMemo } from 'react' +import { countryData } from '@/components/AddMoney/consts' +import ShareButton from '@/components/Global/ShareButton' +import { MantecaDepositResponseData } from '@/types/manteca.types' +import { PaymentInfoRow } from '@/components/Payment/PaymentInfoRow' +import { Icon } from '@/components/Global/Icons/Icon' +import Image from 'next/image' +import { Card } from '@/components/0_Bruddle/Card' + +const MantecaDepositShareDetails = ({ + depositDetails, + source, +}: { + depositDetails: MantecaDepositResponseData + source: 'bank' | 'regionalMethod' +}) => { + const router = useRouter() + const params = useParams() + const currentCountryName = params.country as string + + const currentCountryDetails = useMemo(() => { + // check if we have country params (from dynamic route) + if (currentCountryName) { + return countryData.find( + (country) => country.type === 'country' && country.path === currentCountryName.toLowerCase() + ) + } + // Default to Argentina + return countryData.find((c) => c.id === 'AR') + }, [currentCountryName]) + + const countryCodeForFlag = useMemo(() => { + const countryId = currentCountryDetails?.id || 'AR' + return countryId.toLowerCase() + }, [currentCountryDetails]) + + const depositAddressLabel = useMemo(() => { + switch (currentCountryDetails?.id) { + case 'AR': + return 'CBU' + case 'BR': + return 'Pix Key' + default: + return 'Deposit Address' + } + }, [currentCountryDetails]) + + const depositAddress = depositDetails.details.depositAddress + const depositAlias = depositDetails.details.depositAlias + const depositAmount = depositDetails.stages['1'].thresholdAmount + const usdAmount = depositDetails.stages['3'].amount + const currencySymbol = depositDetails.stages['1'].asset + const exchangeRate = depositDetails.details.price + + const generateShareText = () => { + const textParts = [] + const currencySymbol = currentCountryDetails?.currency || 'ARS' + + textParts.push(`Amount: ${currencySymbol} ${depositAmount}`) + + if (depositAddress) { + textParts.push(`${depositAddressLabel}: ${depositAddress}`) + } + if (depositAlias) { + textParts.push(`Alias: ${depositAlias}`) + } + + return textParts.join('\n') + } + + return ( +
+ router.back()} /> +
+ {/* Amount Display Card */} + +
+
+ {`flag`} +
+ +
+
+
+

+ You're adding +

+

+ {currencySymbol} {depositAmount} +

+
≈ {usdAmount} USD
+
+
+
+

Account details

+ + {depositAddress && } + {depositAlias && } + {currentCountryDetails?.id === 'AR' && ( + <> + + + + )} + + + +
+ + generateShareText()} + title="Bank Transfer Details" + variant="purple" + className="w-full" + > + Share Details + +
+ ) +} + +export default MantecaDepositShareDetails diff --git a/src/components/AddMoney/components/RegionalMethods/MercadoPago/MercadoPagoDepositDetails.tsx b/src/components/AddMoney/components/RegionalMethods/MercadoPago/MercadoPagoDepositDetails.tsx deleted file mode 100644 index 2df420209..000000000 --- a/src/components/AddMoney/components/RegionalMethods/MercadoPago/MercadoPagoDepositDetails.tsx +++ /dev/null @@ -1,79 +0,0 @@ -'use client' - -import NavHeader from '@/components/Global/NavHeader' -import { useParams, useRouter } from 'next/navigation' -import React, { useMemo } from 'react' -import { countryCodeMap, countryData } from '../../../consts' -import MantecaDepositCard from '../../MantecaDepositCard' -import ShareButton from '@/components/Global/ShareButton' -import { MantecaDepositDetails } from '@/types/manteca.types' - -const MercadoPagoDepositDetails = ({ - depositDetails, - source, -}: { - depositDetails: MantecaDepositDetails - source: 'bank' | 'regionalMethod' -}) => { - const router = useRouter() - const params = useParams() - const currentCountryName = params.country as string - - const currentCountryDetails = useMemo(() => { - // check if we have country params (from dynamic route) - if (currentCountryName) { - return countryData.find( - (country) => country.type === 'country' && country.path === currentCountryName.toLowerCase() - ) - } - // Default to Argentina - return countryData.find((c) => c.id === 'AR') - }, [currentCountryName]) - - const countryCodeForFlag = useMemo(() => { - const countryId = currentCountryDetails?.id || 'AR' - return countryId.toLowerCase() - }, [currentCountryDetails]) - - const generateShareText = () => { - const textParts = [] - const currencySymbol = currentCountryDetails?.currency || 'ARS' - - textParts.push(`Amount: ${currencySymbol} ${depositDetails.depositAmount}`) - - if (depositDetails.depositAddress) { - textParts.push(`CBU: ${depositDetails.depositAddress}`) - } - if (depositDetails.depositAlias) { - textParts.push(`Alias: ${depositDetails.depositAlias}`) - } - - return textParts.join('\n') - } - - return ( -
- router.back()} /> - - - - generateShareText()} - title="Bank Transfer Details" - variant="purple" - className="w-full" - > - Share Details - -
- ) -} - -export default MercadoPagoDepositDetails diff --git a/src/components/AddMoney/consts/index.ts b/src/components/AddMoney/consts/index.ts index ef32fbb57..9c21e2293 100644 --- a/src/components/AddMoney/consts/index.ts +++ b/src/components/AddMoney/consts/index.ts @@ -176,16 +176,26 @@ export const UPDATED_DEFAULT_ADD_MONEY_METHODS: SpecificPaymentMethod[] = [ { id: 'crypto-add', icon: 'wallet-outline' as IconName, + path: '/add-money/crypto', title: 'From Crypto', description: 'Usually arrives instantly', isSoon: false, }, { id: 'mercado-pago-add', + path: '/add-money/argentina/manteca', icon: MERCADO_PAGO, title: 'Mercado Pago', - description: 'Popular in LATAM', - isSoon: true, + description: 'Instant transfers', + isSoon: false, + }, + { + id: 'pix-add', + icon: PIX, + path: '/add-money/brazil/manteca', + title: 'Pix', + description: 'Instant transfers', + isSoon: false, }, { id: 'apple-pay-add', @@ -2518,19 +2528,22 @@ export const countryCodeMap: { [key: string]: string } = { USA: 'US', } -const enabledBankTransferCountries = new Set([...Object.values(countryCodeMap), 'US', 'MX', 'AR', 'BO']) +const enabledBankWithdrawCountries = new Set([...Object.values(countryCodeMap), 'US', 'MX', 'AR', 'BO']) + +const enabledBankDepositCountries = new Set([...Object.values(countryCodeMap), 'US', 'AR']) // Helper function to check if a country code is enabled for bank transfers // Handles both 2-letter and 3-letter country codes -const isCountryEnabledForBankTransfer = (countryCode: string): boolean => { +const isCountryEnabledForBankTransfer = (countryCode: string, direction: 'withdraw' | 'deposit'): boolean => { // Direct check for 2-letter codes - if (enabledBankTransferCountries.has(countryCode)) { + const enabledCountries = direction === 'withdraw' ? enabledBankWithdrawCountries : enabledBankDepositCountries + if (enabledCountries.has(countryCode)) { return true } // Check if it's a 3-letter code that maps to an enabled 2-letter code const mappedCode = countryCodeMap[countryCode] - return mappedCode ? enabledBankTransferCountries.has(mappedCode) : false + return mappedCode ? enabledCountries.has(mappedCode) : false } countryData.forEach((country) => { @@ -2618,7 +2631,7 @@ countryData.forEach((country) => { path: isMantecaCountry ? `/withdraw/manteca?method=bank-transfer&country=${country.path}` : `/withdraw/${countryCode.toLowerCase()}/bank`, - isSoon: !isCountryEnabledForBankTransfer(countryCode), + isSoon: !isCountryEnabledForBankTransfer(countryCode, 'withdraw'), }) } @@ -2633,25 +2646,21 @@ countryData.forEach((country) => { // filter add methods: include Mercado Pago only for LATAM countries const currentAddMethods = UPDATED_DEFAULT_ADD_MONEY_METHODS.filter((method) => { if (method.id === 'mercado-pago-add') { - return !!MantecaSupportedExchanges[countryCode as keyof typeof MantecaSupportedExchanges] + return countryCode === 'AR' + } + if (method.id === 'pix-add') { + return countryCode === 'BR' } return true }).map((m) => { const newMethod = { ...m } if (newMethod.id === 'bank-transfer-add') { - newMethod.path = `/add-money/${country.path}/bank` - newMethod.isSoon = !isCountryEnabledForBankTransfer(countryCode) || countryCode === 'MX' - } else if (newMethod.id === 'crypto-add') { - newMethod.path = `/add-money/crypto` - newMethod.isSoon = false - } else if ( - newMethod.id === 'mercado-pago-add' && - MantecaSupportedExchanges[countryCode as keyof typeof MantecaSupportedExchanges] - ) { - newMethod.isSoon = false - newMethod.path = `/add-money/${country.path}/mercadopago` - } else if (newMethod.id === 'mercado-pago-add') { - newMethod.isSoon = true + if (MantecaSupportedExchanges[countryCode as keyof typeof MantecaSupportedExchanges]) { + newMethod.path = `/add-money/${country.path}/manteca` + } else { + newMethod.path = `/add-money/${country.path}/bank` + } + newMethod.isSoon = !isCountryEnabledForBankTransfer(countryCode, 'deposit') } return newMethod }) diff --git a/src/components/Payment/Views/MantecaFulfillment.view.tsx b/src/components/Payment/Views/MantecaFulfillment.view.tsx index 902db6623..ad251d0aa 100644 --- a/src/components/Payment/Views/MantecaFulfillment.view.tsx +++ b/src/components/Payment/Views/MantecaFulfillment.view.tsx @@ -1,12 +1,8 @@ import React, { useEffect, useState } from 'react' -import { MERCADO_PAGO, PIX } from '@/assets' import { CountryData } from '@/components/AddMoney/consts' -import ErrorAlert from '@/components/Global/ErrorAlert' -import MantecaDetailsCard from '@/components/Global/MantecaDetailsCard' -import NavHeader from '@/components/Global/NavHeader' -import PeanutActionDetailsCard from '@/components/Global/PeanutActionDetailsCard' +import MantecaDepositShareDetails from '@/components/AddMoney/components/MantecaDepositShareDetails' import PeanutLoading from '@/components/Global/PeanutLoading' -import ShareButton from '@/components/Global/ShareButton' +import NavHeader from '@/components/Global/NavHeader' import { InitiateMantecaKYCModal } from '@/components/Kyc/InitiateMantecaKYCModal' import { useAuth } from '@/context/authContext' import { useRequestFulfillmentFlow } from '@/context/RequestFulfillmentFlowContext' @@ -16,8 +12,7 @@ import { mantecaApi } from '@/services/manteca' import { useQuery } from '@tanstack/react-query' const MantecaFulfillment = () => { - const { setFulfillUsingManteca, selectedCountry, setSelectedCountry, regionalMethodType } = - useRequestFulfillmentFlow() + const { setFulfillUsingManteca, selectedCountry, setSelectedCountry } = useRequestFulfillmentFlow() const { requestDetails, chargeDetails } = usePaymentStore() const [isKYCModalOpen, setIsKYCModalOpen] = useState(false) const { isUserMantecaKycApproved } = useKycStatus() @@ -47,12 +42,6 @@ const MantecaFulfillment = () => { iso3: 'ARG', } as CountryData - const actionCardLogo = selectedCountry?.id - ? `https://flagcdn.com/w320/${selectedCountry?.id.toLowerCase()}.png` - : regionalMethodType === 'mercadopago' - ? MERCADO_PAGO - : PIX - const handleKycCancel = () => { setIsKYCModalOpen(false) setSelectedCountry(null) @@ -65,14 +54,6 @@ const MantecaFulfillment = () => { } }, [isUserMantecaKycApproved]) - const generateShareText = () => { - const textParts = [] - textParts.push(`CBU: ${depositData?.data?.depositAddress}`) - textParts.push(`Alias: ${depositData?.data?.depositAlias}`) - - return textParts.join('\n') - } - if (isLoadingDeposit) { return } @@ -87,62 +68,8 @@ const MantecaFulfillment = () => { }} /> -
- - - {depositData?.error && } - - {depositData?.data && ( - <> -

Account details

- - + {depositData?.data && } - generateShareText()} - title="Account Details" - variant="purple" - className="w-full" - > - Share Details - - - )} -
{isKYCModalOpen && ( - {transaction.direction !== 'qr_payment' && ( + {transaction.extraDataForDrawer?.receipt?.exchange_rate && ( { - const currencyAmount = - transaction.currency?.amount || transaction.amount.toString() - const currencySymbol = getDisplayCurrencySymbol(transaction.currency!.code) - return `${currencySymbol} ${formatAmount(Number(currencyAmount))}` - })()} - hideBottomBorder={false} + label="Value in USD" + value={`${formatAmount(transaction.amount.toString())} USD`} /> )} - {transaction.direction === 'qr_payment' && - transaction.extraDataForDrawer?.receipt?.exchange_rate && ( - - )} {/* TODO: stop using snake_case!!!!! */} {transaction.extraDataForDrawer?.receipt?.exchange_rate && ( => { + deposit: async ( + params: CreateMantecaOnrampParams + ): Promise<{ data?: MantecaDepositResponseData; error?: string }> => { try { const response = await fetchWithSentry(`${PEANUT_API_URL}/manteca/deposit`, { method: 'POST', diff --git a/src/types/manteca.types.ts b/src/types/manteca.types.ts index 9bf4227ec..38040e779 100644 --- a/src/types/manteca.types.ts +++ b/src/types/manteca.types.ts @@ -1,9 +1,58 @@ import { MantecaAccountType } from '@/constants/manteca.consts' -export interface MantecaDepositDetails { - depositAddress: string - depositAlias: string - depositAmount: string +export interface MantecaDepositResponseData { + id: string + numberId: string + externalId: string + userId: string + userNumberId: string + userExternalId: string + status: string + type: 'RAMP_OPERATION' + details: { + depositAddresses: { + BANK_TRANSFER: string + } + depositAddress: string + depositAlias: string + withdrawCostInAgainst: string + withdrawCostInAsset: string + price: string + priceExpireAt: string + } + currentStage: number + stages: { + '1': { + stageType: 'DEPOSIT' + asset: string + thresholdAmount: string + useOverflow: boolean + expireAt: string + } + '2': { + stageType: string + side: string + type: string + asset: string + against: string + assetAmount: string + price: string + priceCode: string + } + '3': { + stageType: string + network: string + asset: string + amount: string + to: string + destination: { + address: string + bankCode: string + } + } + } + creationTime: string + updatedAt: string } export enum MercadoPagoStep {