Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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: 13 additions & 0 deletions src/components/Claim/Claim.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import * as _consts from './Claim.consts'
import FlowManager from './Link/FlowManager'
import { type PeanutCrossChainRoute } from '@/services/swap'
import { NotFoundClaimLink, WrongPasswordClaimLink, ClaimedView } from './Generic'
import { ClaimBankFlowStep, useClaimBankFlow } from '@/context/ClaimBankFlowContext'
import { useSearchParams } from 'next/navigation'

export const Claim = ({}) => {
const [step, setStep] = useState<_consts.IClaimScreenState>(_consts.INIT_VIEW_STATE)
Expand Down Expand Up @@ -66,6 +68,9 @@ export const Claim = ({}) => {
const senderId = claimLinkData?.sender.userId
const { interactions } = useUserInteractions(senderId ? [senderId] : [])

const { setFlowStep: setClaimBankFlowStep } = useClaimBankFlow()
const searchParams = useSearchParams()

const transactionForDrawer: TransactionDetails | null = useMemo(() => {
if (!claimLinkData) return null

Expand Down Expand Up @@ -254,6 +259,14 @@ export const Claim = ({}) => {
}
}, [linkState, transactionForDrawer])

// redirect to bank flow if user is KYC approved and step is bank
useEffect(() => {
const stepFromURL = searchParams.get('step')
if (user?.user.kycStatus === 'approved' && stepFromURL === 'bank') {
setClaimBankFlowStep(ClaimBankFlowStep.BankCountryList)
}
}, [user])

return (
<PageContainer alignItems="center">
{linkState === _consts.claimLinkStateType.LOADING && <PeanutLoading />}
Expand Down
17 changes: 14 additions & 3 deletions src/components/Claim/Link/Initial.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const InitialClaimLinkView = (props: IClaimScreenProps) => {
isXChain,
setIsXChain,
} = useContext(tokenSelectorContext)
const { claimLink, claimLinkXchain } = useClaimLink()
const { claimLink, claimLinkXchain, removeParamStep } = useClaimLink()
const { isConnected: isPeanutWallet, address, fetchBalance } = useWallet()
const router = useRouter()
const { user } = useAuth()
Expand Down Expand Up @@ -623,6 +623,13 @@ export const InitialClaimLinkView = (props: IClaimScreenProps) => {
}
}

useEffect(() => {
const stepFromURL = searchParams.get('step')
if (user && claimLinkData.status !== 'CLAIMED' && stepFromURL === 'claim') {
handleClaimLink()
}
}, [user, searchParams])

if (claimBankFlowStep) {
return <BankFlowManager {...props} />
}
Expand Down Expand Up @@ -780,9 +787,13 @@ export const InitialClaimLinkView = (props: IClaimScreenProps) => {
modalPanelClassName="max-w-md mx-8"
/>
<GuestVerificationModal
shouldShowVerificationModalOnSignup
secondaryCtaLabel="Claim with other method"
isOpen={showVerificationModal && !user}
onClose={() => setShowVerificationModal(false)}
isOpen={showVerificationModal}
onClose={() => {
removeParamStep()
setShowVerificationModal(false)
}}
description="The sender isn't verified, so please create an account and verify your identity to have the funds deposited to your bank."
/>
</div>
Expand Down
22 changes: 22 additions & 0 deletions src/components/Claim/useClaimLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ import { useWallet } from '@/hooks/wallet/useWallet'
import { isTestnetChain } from '@/utils'
import * as Sentry from '@sentry/nextjs'
import { useAccount } from 'wagmi'
import { usePathname, useSearchParams } from 'next/navigation'

const useClaimLink = () => {
const { fetchBalance } = useWallet()
const { chain: currentChain } = useAccount()
const { switchChainAsync } = useSwitchChain()
const pathname = usePathname()
const searchParams = useSearchParams()

const { setLoadingState } = useContext(loadingStateContext)

Expand Down Expand Up @@ -93,10 +96,29 @@ const useClaimLink = () => {
}
}

const addParamStep = (step: 'bank' | 'claim') => {
const params = new URLSearchParams(searchParams)
params.set('step', step)

const hash = window.location.hash
const newUrl = `${pathname}?${params.toString()}${hash}`
window.history.replaceState(null, '', newUrl)
}

const removeParamStep = () => {
const params = new URLSearchParams(searchParams)
params.delete('step')
const queryString = params.toString()
const newUrl = `${pathname}${queryString ? `?${queryString}` : ''}${window.location.hash}`
window.history.replaceState(null, '', newUrl)
}

return {
claimLink,
claimLinkXchain,
switchNetwork,
addParamStep,
removeParamStep,
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/components/Common/ActionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Button } from '../0_Bruddle'
import { PEANUT_LOGO_BLACK } from '@/assets/illustrations'
import Image from 'next/image'
import { saveRedirectUrl } from '@/utils'
import { useRouter } from 'next/navigation'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { PEANUTMAN_LOGO } from '@/assets/peanut'
import { BankClaimType, useDetermineBankClaimType } from '@/hooks/useDetermineBankClaimType'
import useSavedAccounts from '@/hooks/useSavedAccounts'
Expand All @@ -24,6 +24,7 @@ import { BankRequestType, useDetermineBankRequestType } from '@/hooks/useDetermi
import { GuestVerificationModal } from '../Global/GuestVerificationModal'
import ActionListDaimoPayButton from './ActionListDaimoPayButton'
import { ACTION_METHODS, PaymentMethod } from '@/constants/actionlist.consts'
import useClaimLink from '../Claim/useClaimLink'

interface IActionListProps {
flow: 'claim' | 'request'
Expand All @@ -50,6 +51,7 @@ export default function ActionList({ claimLinkData, isLoggedIn, flow, requestLin
const { requestType } = useDetermineBankRequestType(requesterUserId)
const savedAccounts = useSavedAccounts()
const { usdAmount } = usePaymentStore()
const { addParamStep } = useClaimLink()
const {
setShowRequestFulfilmentBankFlowManager,
setShowExternalWalletFulfilMethods,
Expand All @@ -68,6 +70,7 @@ export default function ActionList({ claimLinkData, isLoggedIn, flow, requestLin
case 'bank':
{
if (claimType === BankClaimType.GuestKycNeeded) {
addParamStep('bank')
setShowVerificationModal(true)
} else {
if (savedAccounts.length) {
Expand Down Expand Up @@ -136,7 +139,7 @@ export default function ActionList({ claimLinkData, isLoggedIn, flow, requestLin
<Button
shadowSize="4"
onClick={() => {
saveRedirectUrl()
addParamStep('claim')
// push to setup page with redirect uri, to prevent the user from losing the flow context
const redirectUri = encodeURIComponent(
window.location.pathname + window.location.search + window.location.hash
Expand Down
4 changes: 4 additions & 0 deletions src/components/Global/ActionModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface ActionModalProps {
descriptionClassName?: string
buttonProps?: ButtonProps
footer?: React.ReactNode
customContent?: React.ReactNode
}

const ActionModal: React.FC<ActionModalProps> = ({
Expand All @@ -64,6 +65,7 @@ const ActionModal: React.FC<ActionModalProps> = ({
descriptionClassName,
buttonProps,
footer,
customContent,
}) => {
const defaultModalPanelClasses = 'max-w-[85%]'
const defaultIconContainerClassName = 'bg-primary-1' // default pink background
Expand Down Expand Up @@ -129,6 +131,8 @@ const ActionModal: React.FC<ActionModalProps> = ({
)}
</div>

{customContent && customContent}

{(checkbox || (ctas && ctas.length > 0)) && (
<div className="w-full space-y-4">
{checkbox && (
Expand Down
7 changes: 6 additions & 1 deletion src/components/Global/GuestLoginCta/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useZeroDev } from '@/hooks/useZeroDev'
import { saveRedirectUrl } from '@/utils'
import { useAppKit } from '@reown/appkit/react'
import * as Sentry from '@sentry/nextjs'
import { useRouter } from 'next/navigation'
import { useRouter, useSearchParams } from 'next/navigation'
import { useEffect } from 'react'

interface GuestLoginCtaProps {
Expand All @@ -18,6 +18,7 @@ const GuestLoginCta = ({ hideConnectWallet = false, view }: GuestLoginCtaProps)
const toast = useToast()
const router = useRouter()
const { open: openReownModal } = useAppKit()
const searchParams = useSearchParams()

// If user already has a passkey address, auto-redirect to avoid double prompting
useEffect(() => {
Expand All @@ -39,6 +40,10 @@ const GuestLoginCta = ({ hideConnectWallet = false, view }: GuestLoginCtaProps)

try {
await handleLogin()
const redirect_uri = searchParams.get('redirect_uri')
if (redirect_uri) {
router.push(redirect_uri)
}
} catch (e) {
toast.error('Error logging in')
Sentry.captureException(e)
Expand Down
6 changes: 6 additions & 0 deletions src/components/Global/GuestVerificationModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ interface GuestVerificationModalProps {
isOpen: boolean
onClose: () => void
secondaryCtaLabel: string
shouldShowVerificationModalOnSignup?: boolean
}

export const GuestVerificationModal = ({
isOpen,
onClose,
description,
secondaryCtaLabel,
shouldShowVerificationModalOnSignup,
}: GuestVerificationModalProps) => {
const router = useRouter()
return (
Expand All @@ -34,6 +36,10 @@ export const GuestVerificationModal = ({
className: 'md:py-2.5',
onClick: () => {
saveRedirectUrl()
if (shouldShowVerificationModalOnSignup) {
router.push('/setup?redirect_uri=/profile/identity-verification')
return
}
router.push('/setup')
},
},
Expand Down
13 changes: 9 additions & 4 deletions src/components/Global/PostSignupActionManager/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useEffect, useState } from 'react'
import ActionModal from '../ActionModal'
import { POST_SIGNUP_ACTIONS } from './post-signup-action.consts'
import { IconName } from '../Icons/Icon'
import { useAuth } from '@/context/authContext'

export const PostSignupActionManager = ({
onActionModalVisibilityChange,
Expand All @@ -21,12 +22,12 @@ export const PostSignupActionManager = ({
action: () => void
} | null>(null)
const router = useRouter()
const { user } = useAuth()

useEffect(() => {
const checkClaimModalAfterKYC = () => {
const redirectUrl = getFromLocalStorage('redirect')
if (redirectUrl) {
if (user?.user.kycStatus === 'approved' && redirectUrl) {
const matchedAction = POST_SIGNUP_ACTIONS.find((action) => action.pathPattern.test(redirectUrl))

if (matchedAction) {
setActionConfig({
...matchedAction.config,
Expand All @@ -39,7 +40,11 @@ export const PostSignupActionManager = ({
setShowModal(true)
}
}
}, [router])
}

useEffect(() => {
checkClaimModalAfterKYC()
}, [router, user])

useEffect(() => {
onActionModalVisibilityChange(showModal)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ export const POST_SIGNUP_ACTIONS = [
// this regex will match any path that contains the word "claim", this helps in determing if the user is coming from a claim link
pathPattern: /claim/,
config: {
title: 'Claim your money',
description: `You're almost done! Tap Claim Funds to move the money into your new Peanut Wallet.`,
cta: 'Claim Funds',
icon: 'dollar' as IconName,
title: 'Verification complete!',
description: `Your identity has been successfully verified. You can now claim money directly to your bank account.`,
cta: 'Claim to bank',
icon: 'check' as IconName,
},
},
]
9 changes: 8 additions & 1 deletion src/components/Setup/Views/SetupPasskey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useZeroDev } from '@/hooks/useZeroDev'
import { useSetupFlow } from '@/hooks/useSetupFlow'
import { useAuth } from '@/context/authContext'
import { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation'
import { useRouter, useSearchParams } from 'next/navigation'
import * as Sentry from '@sentry/nextjs'
import { WalletProviderType } from '@/interfaces'
import { WebAuthnError } from '@simplewebauthn/browser'
Expand All @@ -22,6 +22,7 @@ const SetupPasskey = () => {
const { addAccount } = useAuth()
const [error, setError] = useState<string | null>(null)
const router = useRouter()
const searchParams = useSearchParams()

useEffect(() => {
if (address && user) {
Expand All @@ -32,6 +33,12 @@ const SetupPasskey = () => {
telegramHandle: telegramHandle.length > 0 ? telegramHandle : undefined,
})
.then(() => {
const redirect_uri = searchParams.get('redirect_uri')
if (redirect_uri) {
router.push(redirect_uri)
return
}

const localStorageRedirect = getFromLocalStorage('redirect')
// redirect based on post signup action config
if (localStorageRedirect) {
Expand Down
16 changes: 12 additions & 4 deletions src/components/Setup/Views/Welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useSetupFlow } from '@/hooks/useSetupFlow'
import { useZeroDev } from '@/hooks/useZeroDev'
import { getFromLocalStorage } from '@/utils'
import * as Sentry from '@sentry/nextjs'
import { useRouter } from 'next/navigation'
import { useRouter, useSearchParams } from 'next/navigation'
import { useEffect } from 'react'

const WelcomeStep = () => {
Expand All @@ -16,6 +16,7 @@ const WelcomeStep = () => {
const { user } = useAuth()
const { push } = useRouter()
const toast = useToast()
const searchParams = useSearchParams()

useEffect(() => {
if (!!user) {
Expand Down Expand Up @@ -53,9 +54,16 @@ const WelcomeStep = () => {
className="h-11"
variant="primary-soft"
onClick={() => {
handleLogin().catch((e) => {
handleError(e)
})
handleLogin()
.then(() => {
const redirect_uri = searchParams.get('redirect_uri')
if (redirect_uri) {
push(redirect_uri)
}
})
.catch((e) => {
handleError(e)
})
}}
>
Log In
Expand Down
3 changes: 2 additions & 1 deletion src/utils/general.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,8 @@ export function isStableCoin(tokenSymbol: string): boolean {

export const saveRedirectUrl = () => {
const currentUrl = new URL(window.location.href)
saveToLocalStorage('redirect', `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`)
const relativeUrl = currentUrl.href.replace(currentUrl.origin, '')
saveToLocalStorage('redirect', relativeUrl)
}

export const formatPaymentStatus = (status: string): string => {
Expand Down
Loading