Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a913608
feat: handle send link claims to bank account for peanut users (#1078)
kushagrasarathe Aug 13, 2025
35a7a15
remove duplicate debounce code and use `useDebounce` hook instead (#1…
Zishan-7 Aug 13, 2025
ee6e749
Landing page v2.1 (#1089)
Zishan-7 Aug 14, 2025
03878b0
[TASK-13186] refactor: use networkName instead of axelarChainName (#1…
jjramirezn Aug 14, 2025
6adb9c3
fix: onramp currency (#1096)
Zishan-7 Aug 15, 2025
a65bddd
fix: stretched favicon (#1099)
Zishan-7 Aug 15, 2025
be50ecb
[TASK-13971] fix: scientific notation in eip681 parsing (#1097)
jjramirezn Aug 15, 2025
9e8197d
pull iban hotfix (#1100)
Zishan-7 Aug 15, 2025
e92923c
fix: claim flow bugs (#1102)
kushagrasarathe Aug 18, 2025
d4bcddf
Fix back button not working on /profile (#1101)
Zishan-7 Aug 18, 2025
8e51429
fix: send link claims to us bank accounts (#1108)
kushagrasarathe Aug 19, 2025
d6d974b
Sync Landing page changes (#1111)
Zishan-7 Aug 20, 2025
57a2de2
fix: us bank claims after kyc for logged in users (#1112)
kushagrasarathe Aug 20, 2025
0a5ac02
fix: trim account form inputs for spaces (#1114)
kushagrasarathe Aug 20, 2025
46200bf
[TASK-14107] fix: don't allow claiming on xChain if route is not foun…
jjramirezn Aug 20, 2025
71ee857
feat: handle redirect uri when on unsupported browsers (#1117)
kushagrasarathe Aug 21, 2025
90a20e1
remove animation (#1118)
Zishan-7 Aug 21, 2025
ede3e32
Merge remote-tracking branch 'origin/peanut-wallet' into chore/prod-r…
jjramirezn Aug 21, 2025
e27fc3c
fix: formatting
jjramirezn Aug 21, 2025
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
2 changes: 1 addition & 1 deletion src/app/(mobile-ui)/claim/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export async function generateMetadata({
description,
...(siteUrl ? { metadataBase: new URL(siteUrl) } : {}),
icons: {
icon: '/logo-favicon.png',
icon: '/favicon.ico',
},
openGraph: {
title,
Expand Down
8 changes: 4 additions & 4 deletions src/app/(mobile-ui)/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ import { AccountType } from '@/interfaces'
import { formatUnits } from 'viem'
import { PEANUT_WALLET_TOKEN_DECIMALS } from '@/constants'
import { PostSignupActionManager } from '@/components/Global/PostSignupActionManager'
import { useGuestFlow } from '@/context/GuestFlowContext'
import { useWithdrawFlow } from '@/context/WithdrawFlowContext'
import { useClaimBankFlow } from '@/context/ClaimBankFlowContext'

const BALANCE_WARNING_THRESHOLD = parseInt(process.env.NEXT_PUBLIC_BALANCE_WARNING_THRESHOLD ?? '500')
const BALANCE_WARNING_EXPIRY = parseInt(process.env.NEXT_PUBLIC_BALANCE_WARNING_EXPIRY ?? '1814400') // 21 days in seconds
Expand All @@ -48,7 +48,7 @@ export default function Home() {
const { balance, address, isFetchingBalance, isFetchingRewardBalance } = useWallet()
const { rewardWalletBalance } = useWalletStore()
const [isRewardsModalOpen, setIsRewardsModalOpen] = useState(false)
const { resetGuestFlow } = useGuestFlow()
const { resetFlow: resetClaimBankFlow } = useClaimBankFlow()
const { resetWithdrawFlow } = useWithdrawFlow()
const [isBalanceHidden, setIsBalanceHidden] = useState(() => {
const prefs = getUserPreferences()
Expand Down Expand Up @@ -84,9 +84,9 @@ export default function Home() {
const isLoading = isFetchingUser && !username

useEffect(() => {
resetGuestFlow()
resetClaimBankFlow()
resetWithdrawFlow()
}, [resetGuestFlow, resetWithdrawFlow])
}, [resetClaimBankFlow, resetWithdrawFlow])

useEffect(() => {
// We have some users that didn't have the peanut wallet created
Expand Down
2 changes: 1 addition & 1 deletion src/app/(mobile-ui)/request/pay/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export async function generateMetadata({
title,
description: 'Request cryptocurrency from friends, family, or anyone else using Peanut on any chain.',
icons: {
icon: '/logo-favicon.png',
icon: '/favicon.ico',
},
openGraph: {
images: [
Expand Down
2 changes: 1 addition & 1 deletion src/app/[...recipient]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export async function generateMetadata({ params, searchParams }: any) {
description,
...(siteUrl ? { metadataBase: new URL(siteUrl) } : {}),
icons: {
icon: '/logo-favicon.png',
icon: '/favicon.ico',
},
openGraph: {
title,
Expand Down
17 changes: 9 additions & 8 deletions src/app/actions/squid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@ const getSquidTokensCache = unstable_cache(
)

export const getSquidChainsAndTokens = unstable_cache(
async (): Promise<Record<string, interfaces.ISquidChain & { tokens: interfaces.ISquidToken[] }>> => {
async (): Promise<
Record<string, interfaces.ISquidChain & { networkName: string; tokens: interfaces.ISquidToken[] }>
> => {
const [chains, tokens] = await Promise.all([getSquidChainsCache(), getSquidTokensCache()])

const chainsById = chains.reduce<Record<string, interfaces.ISquidChain & { tokens: interfaces.ISquidToken[] }>>(
(acc, chain) => {
acc[chain.chainId] = { ...chain, tokens: [] }
return acc
},
{}
)
const chainsById = chains.reduce<
Record<string, interfaces.ISquidChain & { networkName: string; tokens: interfaces.ISquidToken[] }>
>((acc, chain) => {
acc[chain.chainId] = { ...(chain as interfaces.ISquidChain & { networkName: string }), tokens: [] }
return acc
}, {})

tokens.forEach((token) => {
if (token.active && token.chainId in chainsById) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/exchange/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Footer from '@/components/LandingPage/Footer'
export default function ExchangePage() {
return (
<Layout className="enable-select !m-0 w-full !p-0">
<NoFees isExchangePage />
<NoFees />
<Footer />
</Layout>
)
Expand Down
1 change: 1 addition & 0 deletions src/components/0_Bruddle/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client'
import React, { forwardRef, useEffect, useRef, useState, useCallback } from 'react'
import { twMerge } from 'tailwind-merge'
import { Icon, IconName } from '../Global/Icons/Icon'
Expand Down
3 changes: 1 addition & 2 deletions src/components/AddMoney/components/DepositMethodList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { CardPosition } from '@/components/Global/Card'
import AvatarWithBadge from '@/components/Profile/AvatarWithBadge'
import { SearchResultCard } from '@/components/SearchUsers/SearchResultCard'
import { IconName } from '@/components/Global/Icons/Icon'
import Image from 'next/image'
import { twMerge } from 'tailwind-merge'
import { countryCodeMap } from '../consts'
Expand Down Expand Up @@ -38,7 +37,7 @@ export const DepositMethodList = ({ methods, onItemClick, isAllMethodsView = fal
if (isSingleOverall) {
determinedPosition = 'single'
} else if (isFirstOverall) {
determinedPosition = 'first'
determinedPosition = isCryptoAtSlot0 && isAllMethodsView ? 'single' : 'first'
} else if (isCryptoAtSlot0 && isCurrentMethodCountry && index === 1 && isAllMethodsView) {
// if crypto card is at methods[0], and this is the country card at methods[1],
// treat this country card as 'first' in its own group.
Expand Down
4 changes: 2 additions & 2 deletions src/components/AddMoney/views/NetworkSelection.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const NetworkSelectionView: React.FC<NetworkSelectionViewProps> = ({ onNetworkSe
<NetworkListItem
key={index}
chainId={squidChainDetails?.chainId ?? network.chainId}
name={squidChainDetails?.axelarChainName ?? network.name}
name={squidChainDetails?.networkName ?? network.name}
iconUrl={squidChainDetails?.chainIconURI ?? network.iconUrl}
isComingSoon={isComingSoon}
iconClassName={
Expand All @@ -60,7 +60,7 @@ const NetworkSelectionView: React.FC<NetworkSelectionViewProps> = ({ onNetworkSe
onClick={() =>
onNetworkSelect({
chainId: squidChainDetails?.chainId ?? network.chainId,
name: squidChainDetails?.axelarChainName ?? network.name,
name: squidChainDetails?.networkName ?? network.name,
iconUrl: squidChainDetails?.chainIconURI ?? network.iconUrl,
})
}
Expand Down
54 changes: 18 additions & 36 deletions src/components/AddWithdraw/AddWithdrawCountriesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ import { useEffect, useMemo, useRef, useState } from 'react'
import { InitiateKYCModal } from '@/components/Kyc'
import { DynamicBankAccountForm, IBankAccountDetails } from './DynamicBankAccountForm'
import { addBankAccount, updateUserById } from '@/app/actions/users'
import { jsonParse, jsonStringify } from '@/utils/general.utils'
import { KYCStatus } from '@/utils/bridge-accounts.utils'
import { AddBankAccountPayload } from '@/app/actions/types/users.types'
import { useWebSocket } from '@/hooks/useWebSocket'
import { useWithdrawFlow } from '@/context/WithdrawFlowContext'
import { useOnrampFlow } from '@/context/OnrampFlowContext'
import { Account } from '@/interfaces'
import PeanutLoading from '../Global/PeanutLoading'
import { getCountryCodeForWithdraw } from '@/utils/withdraw.utils'
Expand All @@ -39,10 +37,8 @@ const AddWithdrawCountriesList = ({ flow }: AddWithdrawCountriesListProps) => {
const params = useParams()
const { user, fetchUser } = useAuth()
const { setSelectedBankAccount, amountToWithdraw } = useWithdrawFlow()
const { setFromBankSelected } = useOnrampFlow()
const [view, setView] = useState<'list' | 'form'>('list')
const [isKycModalOpen, setIsKycModalOpen] = useState(false)
const [cachedBankDetails, setCachedBankDetails] = useState<Partial<IBankAccountDetails> | null>(null)
const formRef = useRef<{ handleSubmit: () => void }>(null)
const [liveKycStatus, setLiveKycStatus] = useState<KYCStatus | undefined>(user?.user?.kycStatus as KYCStatus)

Expand Down Expand Up @@ -72,18 +68,6 @@ const AddWithdrawCountriesList = ({ flow }: AddWithdrawCountriesListProps) => {
(country) => country.type === 'country' && country.path === countrySlugFromUrl
)

useEffect(() => {
if (user?.user.userId) {
const item = sessionStorage.getItem(`temp-bank-account-${user.user.userId}`)
const data = item ? jsonParse(item) : null
const currentStatus = liveKycStatus || user.user.kycStatus
if (data && currentStatus === 'approved' && !cachedBankDetails) {
setCachedBankDetails(data)
setView('form')
}
}
}, [user, liveKycStatus, cachedBankDetails])

const handleFormSubmit = async (
payload: AddBankAccountPayload,
rawData: IBankAccountDetails
Expand Down Expand Up @@ -130,9 +114,6 @@ const AddWithdrawCountriesList = ({ flow }: AddWithdrawCountriesListProps) => {
setSelectedBankAccount(newAccountFromResponse)
}

if (user?.user.userId) {
sessionStorage.removeItem(`temp-bank-account-${user.user.userId}`)
}
if (currentCountry) {
router.push(`/withdraw/${currentCountry.path}/bank`)
}
Expand All @@ -157,20 +138,17 @@ const AddWithdrawCountriesList = ({ flow }: AddWithdrawCountriesListProps) => {

// scenario (2): if the user hasn't completed kyc yet
if (!isUserKycVerified) {
const { firstName, lastName, email, ...detailsToSave } = rawData
if (user?.user.userId) {
sessionStorage.setItem(`temp-bank-account-${user.user.userId}`, jsonStringify(detailsToSave))
}
setIsKycModalOpen(true)
}

return {}
}

const handleKycSuccess = () => {
setIsKycModalOpen(false)
if (formRef.current) {
formRef.current.handleSubmit()
// only transition to form if this component initiated the KYC modal
if (isKycModalOpen) {
setIsKycModalOpen(false)
setView('form')
}
}

Expand Down Expand Up @@ -213,16 +191,20 @@ const AddWithdrawCountriesList = ({ flow }: AddWithdrawCountriesListProps) => {
if (view === 'form') {
return (
<div className="flex min-h-[inherit] flex-col justify-normal gap-8">
<NavHeader title={'Withdraw'} onPrev={() => setView('list')} />

<div className="flex h-full w-full flex-1 flex-col justify-start gap-4">
<DynamicBankAccountForm
ref={formRef}
country={getCountryCodeForWithdraw(currentCountry.id)}
onSuccess={handleFormSubmit}
initialData={cachedBankDetails ?? {}}
/>
</div>
<NavHeader
title={flow === 'withdraw' ? 'Withdraw' : 'Add money'}
onPrev={() => {
// ensure kyc modal isn't open so late success events don't flip view
setIsKycModalOpen(false)
setView('list')
}}
/>
<DynamicBankAccountForm
ref={formRef}
country={getCountryCodeForWithdraw(currentCountry.id)}
onSuccess={handleFormSubmit}
initialData={{}}
/>
Comment on lines +203 to +207
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: Passing 3-letter code breaks MX handling in DynamicBankAccountForm.

DynamicBankAccountForm treats Mexico as country === 'MX'. Passing MEX via getCountryCodeForWithdraw causes MX to be misclassified as IBAN and fails CLABE validation.

Apply:

-                <DynamicBankAccountForm
-                    ref={formRef}
-                    country={getCountryCodeForWithdraw(currentCountry.id)}
+                <DynamicBankAccountForm
+                    ref={formRef}
+                    country={countryCodeMap[currentCountry.id] === 'MX' ? 'MX' : currentCountry.id}
                     onSuccess={handleFormSubmit}
                     initialData={{}}
                 />

…and remove the now-unused import:

-import { getCountryCodeForWithdraw } from '@/utils/withdraw.utils'

Committable suggestion skipped: line range outside the PR's diff.

<InitiateKYCModal
isOpen={isKycModalOpen}
onClose={() => setIsKycModalOpen(false)}
Expand Down
Loading
Loading