diff --git a/src/app/(mobile-ui)/qr-pay/page.tsx b/src/app/(mobile-ui)/qr-pay/page.tsx
index aad1f6bf2..6d90fbe77 100644
--- a/src/app/(mobile-ui)/qr-pay/page.tsx
+++ b/src/app/(mobile-ui)/qr-pay/page.tsx
@@ -2,7 +2,7 @@
import { useSearchParams, useRouter } from 'next/navigation'
import { useState, useCallback, useMemo, useEffect, useContext } from 'react'
-import { Card } from '@/components/0_Bruddle/Card'
+
import { Button } from '@/components/0_Bruddle/Button'
import { Icon } from '@/components/Global/Icons/Icon'
import { mantecaApi } from '@/services/manteca'
@@ -29,6 +29,8 @@ import { QrKycState, useQrKycGate } from '@/hooks/useQrKycGate'
import ActionModal from '@/components/Global/ActionModal'
import { saveRedirectUrl } from '@/utils/general.utils'
import { MantecaGeoSpecificKycModal } from '@/components/Kyc/InitiateMantecaKYCModal'
+import { PeanutDoesntStoreAnyPersonalInformation } from '@/components/Kyc/KycVerificationInProgressModal'
+import Card from '@/components/Global/Card'
const MANTECA_DEPOSIT_ADDRESS = '0x959e088a09f61aB01cb83b0eBCc74b2CF6d62053'
const MAX_QR_PAYMENT_AMOUNT = '200'
@@ -216,18 +218,18 @@ export default function QRPayPage() {
if (!!errorInitiatingPayment) {
return (
-
-
- Unable to get QR details
-
+
+
+
Unable to get QR details
+
{errorInitiatingPayment || 'An error occurred while getting the QR details.'}
-
-
-
- router.back()} variant="purple">
- Go Back
-
-
+
+
+
+
+ router.back()} variant="purple">
+ Go Back
+
)
@@ -273,11 +275,7 @@ export default function QRPayPage() {
icon: 'check-circle',
},
]}
- footer={
-
- Peanut doesn't store any personal information
-
- }
+ footer={ }
/>
)
diff --git a/src/app/[...recipient]/client.tsx b/src/app/[...recipient]/client.tsx
index aef205f4e..b65cfbb49 100644
--- a/src/app/[...recipient]/client.tsx
+++ b/src/app/[...recipient]/client.tsx
@@ -394,8 +394,7 @@ export default function PaymentPage({ recipient, flow = 'request_pay' }: Props)
}, [transactionForDrawer, currentView, dispatch, openTransactionDetails, isExternalWalletFlow, chargeId])
const showActionList =
- flow !== 'direct_pay' || // Always show for non-direct-pay flows
- (flow === 'direct_pay' && !user) || // Show for direct-pay when user is not logged in
+ (flow !== 'direct_pay' || (flow === 'direct_pay' && !user)) && // Show for direct-pay when user is not logged in
!fulfillUsingManteca // Show when not fulfilling using Manteca
// Send to bank step if its mentioned in the URL and guest KYC is not needed
useEffect(() => {
diff --git a/src/components/Claim/Link/MantecaFlowManager.tsx b/src/components/Claim/Link/MantecaFlowManager.tsx
index ead46215f..d32d6556f 100644
--- a/src/components/Claim/Link/MantecaFlowManager.tsx
+++ b/src/components/Claim/Link/MantecaFlowManager.tsx
@@ -5,12 +5,16 @@ import NavHeader from '@/components/Global/NavHeader'
import PeanutActionDetailsCard from '@/components/Global/PeanutActionDetailsCard'
import { useClaimBankFlow } from '@/context/ClaimBankFlowContext'
import { ClaimLinkData } from '@/services/sendLinks'
-import { FC, useState } from 'react'
+import { FC, useEffect, useState } from 'react'
import MantecaDetailsStep from './views/MantecaDetailsStep.view'
import { MercadoPagoStep } from '@/types/manteca.types'
import MantecaReviewStep from './views/MantecaReviewStep'
import { Button } from '@/components/0_Bruddle'
import { useRouter } from 'next/navigation'
+import useKycStatus from '@/hooks/useKycStatus'
+import { InitiateMantecaKYCModal } from '@/components/Kyc/InitiateMantecaKYCModal'
+import { useAuth } from '@/context/authContext'
+import { CountryData } from '@/components/AddMoney/consts'
interface MantecaFlowManagerProps {
claimLinkData: ClaimLinkData
@@ -19,12 +23,38 @@ interface MantecaFlowManagerProps {
}
const MantecaFlowManager: FC = ({ claimLinkData, amount, attachment }) => {
- const { setClaimToMercadoPago } = useClaimBankFlow()
+ const { setClaimToMercadoPago, selectedCountry } = useClaimBankFlow()
const [currentStep, setCurrentStep] = useState(MercadoPagoStep.DETAILS)
const router = useRouter()
const [destinationAddress, setDestinationAddress] = useState('')
+ const [isKYCModalOpen, setIsKYCModalOpen] = useState(false)
+ const argentinaCountryData = {
+ id: 'AR',
+ type: 'country',
+ title: 'Argentina',
+ currency: 'ARS',
+ path: 'argentina',
+ iso2: 'AR',
+ iso3: 'ARG',
+ } as CountryData
+
+ const { isUserMantecaKycApproved } = useKycStatus()
+ const { fetchUser } = useAuth()
const isSuccess = currentStep === MercadoPagoStep.SUCCESS
+ const selectedCurrency = selectedCountry?.currency || 'ARS'
+ const logo = selectedCountry?.id ? undefined : MERCADO_PAGO
+
+ const handleKycCancel = () => {
+ setIsKYCModalOpen(false)
+ onPrev()
+ }
+
+ useEffect(() => {
+ if (!isUserMantecaKycApproved) {
+ setIsKYCModalOpen(true)
+ }
+ }, [isUserMantecaKycApproved])
const renderStepDetails = () => {
if (currentStep === MercadoPagoStep.DETAILS) {
@@ -43,6 +73,7 @@ const MantecaFlowManager: FC = ({ claimLinkData, amount
claimLink={claimLinkData.link}
destinationAddress={destinationAddress}
amount={amount}
+ currency={selectedCurrency}
/>
)
}
@@ -88,10 +119,25 @@ const MantecaFlowManager: FC = ({ claimLinkData, amount
tokenSymbol={claimLinkData.tokenSymbol}
message={attachment.message}
fileUrl={attachment.attachmentUrl}
- logo={isSuccess ? undefined : MERCADO_PAGO}
+ logo={isSuccess ? undefined : logo}
+ countryCodeForFlag={selectedCountry?.id.toLowerCase()}
/>
{renderStepDetails()}
+
+ {isKYCModalOpen && (
+ {
+ // close the modal and let the user continue with amount input
+ setIsKYCModalOpen(false)
+ fetchUser()
+ }}
+ country={selectedCountry || argentinaCountryData}
+ />
+ )}
)
diff --git a/src/components/Claim/Link/views/MantecaReviewStep.tsx b/src/components/Claim/Link/views/MantecaReviewStep.tsx
index 2ea5bb388..fe1c882a0 100644
--- a/src/components/Claim/Link/views/MantecaReviewStep.tsx
+++ b/src/components/Claim/Link/views/MantecaReviewStep.tsx
@@ -14,12 +14,19 @@ interface MantecaReviewStepProps {
claimLink: string
destinationAddress: string
amount: string
+ currency: string
}
-const MantecaReviewStep: FC = ({ setCurrentStep, claimLink, destinationAddress, amount }) => {
+const MantecaReviewStep: FC = ({
+ setCurrentStep,
+ claimLink,
+ destinationAddress,
+ amount,
+ currency,
+}) => {
const [isSubmitting, setIsSubmitting] = useState(false)
const [error, setError] = useState(null)
- const { price, isLoading } = useCurrency('ARS') // TODO: change to the currency of the selected Method
+ const { price, isLoading } = useCurrency(currency)
const detailsCardRows: MantecaCardRow[] = [
{
@@ -31,7 +38,7 @@ const MantecaReviewStep: FC = ({ setCurrentStep, claimLi
{
key: 'exchangeRate',
label: 'Exchange Rate',
- value: `1 USD = ${price?.buy} ARS`,
+ value: `1 USD = ${price?.buy} ${currency}`,
},
{
key: 'fee',
@@ -55,7 +62,7 @@ const MantecaReviewStep: FC = ({ setCurrentStep, claimLi
amount: amount.replace(/,/g, ''),
destinationAddress,
txHash,
- currency: 'ARS', // TODO: source-selected currency
+ currency,
})
if (withdrawError || !data) {
setError(withdrawError || 'Something went wrong. Please contact Support')
diff --git a/src/components/Common/CountryList.tsx b/src/components/Common/CountryList.tsx
index 22ab13a5e..f79635851 100644
--- a/src/components/Common/CountryList.tsx
+++ b/src/components/Common/CountryList.tsx
@@ -135,7 +135,7 @@ export const CountryList = ({
isSupported = isBridgeSupportedCountry || isMantecaSupportedCountry
} else if (viewMode === 'claim-request') {
// support all countries
- isSupported = isBridgeSupportedCountry
+ isSupported = isBridgeSupportedCountry || isMantecaSupportedCountry
} else {
// support all countries
isSupported = true
diff --git a/src/components/Common/CountryListRouter.tsx b/src/components/Common/CountryListRouter.tsx
index e11b4ae85..9f66128d7 100644
--- a/src/components/Common/CountryListRouter.tsx
+++ b/src/components/Common/CountryListRouter.tsx
@@ -9,7 +9,7 @@ import { formatUnits } from 'viem'
import { formatTokenAmount, printableAddress } from '@/utils/general.utils'
import { CountryList } from '@/components/Common/CountryList'
import { ClaimLinkData } from '@/services/sendLinks'
-import { CountryData } from '@/components/AddMoney/consts'
+import { CountryData, MantecaSupportedExchanges } from '@/components/AddMoney/consts'
import useSavedAccounts from '@/hooks/useSavedAccounts'
import { ParsedURL } from '@/lib/url-parser/types/payment'
import { useCallback, useMemo } from 'react'
@@ -41,12 +41,18 @@ export const CountryListRouter = ({
requestLinkData,
inputTitle,
}: ICountryListRouterViewProps) => {
- const { setFlowStep: setClaimBankFlowStep, setSelectedCountry } = useClaimBankFlow()
+ const {
+ setFlowStep: setClaimBankFlowStep,
+ setSelectedCountry,
+ setClaimToMercadoPago,
+ setFlowStep,
+ } = useClaimBankFlow()
const {
setFlowStep: setRequestFulfilmentBankFlowStep,
setShowRequestFulfilmentBankFlowManager,
setSelectedCountry: setSelectedCountryForRequest,
setShowVerificationModal,
+ setFulfillUsingManteca,
} = useRequestFulfillmentFlow()
const savedAccounts = useSavedAccounts()
const { chargeDetails } = usePaymentStore()
@@ -54,10 +60,20 @@ export const CountryListRouter = ({
const { user } = useAuth()
const handleCountryClick = (country: CountryData) => {
+ const isMantecaSupportedCountry = Object.keys(MantecaSupportedExchanges).includes(country.id)
if (flow === 'claim') {
setSelectedCountry(country)
- setClaimBankFlowStep(ClaimBankFlowStep.BankDetailsForm)
+ if (isMantecaSupportedCountry) {
+ setFlowStep(null) // reset the flow step to initial view first
+ setClaimToMercadoPago(true)
+ } else {
+ setClaimBankFlowStep(ClaimBankFlowStep.BankDetailsForm)
+ }
} else if (flow === 'request') {
+ if (isMantecaSupportedCountry) {
+ setShowRequestFulfilmentBankFlowManager(false)
+ setFulfillUsingManteca(true)
+ }
setSelectedCountryForRequest(country)
if (requestType === BankRequestType.PayerKycNeeded) {
diff --git a/src/components/Global/PeanutActionDetailsCard/index.tsx b/src/components/Global/PeanutActionDetailsCard/index.tsx
index 3b1e875c7..594441e7f 100644
--- a/src/components/Global/PeanutActionDetailsCard/index.tsx
+++ b/src/components/Global/PeanutActionDetailsCard/index.tsx
@@ -165,13 +165,15 @@ export default function PeanutActionDetailsCard({
const isWithdrawBankAccount = transactionType === 'WITHDRAW_BANK_ACCOUNT' && recipientType === 'BANK_ACCOUNT'
const isAddBankAccount = transactionType === 'ADD_MONEY_BANK_ACCOUNT'
const isClaimLinkBankAccount = transactionType === 'CLAIM_LINK_BANK_ACCOUNT' && recipientType === 'BANK_ACCOUNT'
+ const isRegionalMethodClaim = transactionType === 'REGIONAL_METHOD_CLAIM'
const withdrawBankIcon = () => {
const imgSrc = logo ? logo : `https://flagcdn.com/w320/${countryCodeForFlag}.png`
- if (isWithdrawBankAccount || isAddBankAccount || isClaimLinkBankAccount)
+
+ if (isWithdrawBankAccount || isAddBankAccount || isClaimLinkBankAccount || isRegionalMethodClaim)
return (
- {countryCodeForFlag && (
+ {(countryCodeForFlag || logo) && (
)}
-
-
-
+ {!isRegionalMethodClaim && (
+
+
+
+ )}
)
return undefined
@@ -192,7 +196,8 @@ export default function PeanutActionDetailsCard({
- {viewType !== 'SUCCESS' && (isWithdrawBankAccount || isAddBankAccount || isClaimLinkBankAccount) ? (
+ {viewType !== 'SUCCESS' &&
+ (isWithdrawBankAccount || isAddBankAccount || isClaimLinkBankAccount || isRegionalMethodClaim) ? (
withdrawBankIcon()
) : (
{
- const { setFulfillUsingManteca } = useRequestFulfillmentFlow()
+ const { setFulfillUsingManteca, selectedCountry, setSelectedCountry } = useRequestFulfillmentFlow()
const { requestDetails, chargeDetails } = usePaymentStore()
+ const [isKYCModalOpen, setIsKYCModalOpen] = useState(false)
+ const { isUserMantecaKycApproved } = useKycStatus()
+ const { fetchUser } = useAuth()
const { data: depositData, isLoading: isLoadingDeposit } = useQuery({
queryKey: ['manteca-deposit', chargeDetails?.uuid],
queryFn: () =>
mantecaApi.deposit({
usdAmount: requestDetails?.tokenAmount || chargeDetails?.tokenAmount || '0',
- currency: 'ARS',
+ currency: selectedCountry?.currency || 'ARS',
chargeId: chargeDetails?.uuid,
}),
refetchOnWindowFocus: false,
staleTime: Infinity, // don't refetch the data
- enabled: Boolean(chargeDetails?.uuid),
+ enabled: Boolean(chargeDetails?.uuid) && isUserMantecaKycApproved,
})
+ const argentinaCountryData = {
+ id: 'AR',
+ type: 'country',
+ title: 'Argentina',
+ currency: 'ARS',
+ path: 'argentina',
+ iso2: 'AR',
+ iso3: 'ARG',
+ } as CountryData
+
+ const actionCardLogo = selectedCountry?.id
+ ? `https://flagcdn.com/w320/${selectedCountry?.id.toLowerCase()}.png`
+ : MERCADO_PAGO
+
const generateShareText = () => {
const textParts = []
textParts.push(`CBU: ${depositData?.data?.depositAddress}`)
@@ -35,6 +56,18 @@ const MantecaFulfillment = () => {
return textParts.join('\n')
}
+ const handleKycCancel = () => {
+ setIsKYCModalOpen(false)
+ setSelectedCountry(null)
+ setFulfillUsingManteca(false)
+ }
+
+ useEffect(() => {
+ if (!isUserMantecaKycApproved) {
+ setIsKYCModalOpen(true)
+ }
+ }, [isUserMantecaKycApproved])
+
if (isLoadingDeposit) {
return
}
@@ -44,6 +77,7 @@ const MantecaFulfillment = () => {
{
+ setSelectedCountry(null)
setFulfillUsingManteca(false)
}}
/>
@@ -58,7 +92,8 @@ const MantecaFulfillment = () => {
tokenSymbol={requestDetails?.tokenSymbol || 'USDC'}
message={requestDetails?.reference || chargeDetails?.requestLink?.reference || ''}
fileUrl={requestDetails?.attachmentUrl || chargeDetails?.requestLink?.attachmentUrl || ''}
- logo={MERCADO_PAGO}
+ logo={actionCardLogo}
+ countryCodeForFlag={selectedCountry?.id.toLowerCase()}
/>
{depositData?.error && }
@@ -103,6 +138,19 @@ const MantecaFulfillment = () => {
>
)}
+ {isKYCModalOpen && (
+
{
+ // close the modal and let the user continue with amount input
+ setIsKYCModalOpen(false)
+ fetchUser()
+ }}
+ country={selectedCountry || argentinaCountryData}
+ />
+ )}
)
}
diff --git a/src/hooks/useCurrency.ts b/src/hooks/useCurrency.ts
index a103fa8dd..d200d7bc4 100644
--- a/src/hooks/useCurrency.ts
+++ b/src/hooks/useCurrency.ts
@@ -22,7 +22,7 @@ export const useCurrency = (currencyCode: string | null) => {
const [code, setCode] = useState(currencyCode?.toUpperCase() ?? null)
const [symbol, setSymbol] = useState(null)
const [price, setPrice] = useState<{ buy: number; sell: number } | null>(null)
- const [isLoading, setIsLoading] = useState(false)
+ const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
if (!code) {
diff --git a/src/services/manteca.ts b/src/services/manteca.ts
index 1b5cbd522..f0f9aaab7 100644
--- a/src/services/manteca.ts
+++ b/src/services/manteca.ts
@@ -177,6 +177,7 @@ export const mantecaApi = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${Cookies.get('jwt-token')}`,
+ 'api-key': 'DRdzuEiRvTtbFYKGahIdFUHuwhYzl1vo',
},
body: JSON.stringify({
usdAmount: params.usdAmount,