diff --git a/src/app/(setup)/layout.tsx b/src/app/(setup)/layout.tsx index fccb3a21..972e1c82 100644 --- a/src/app/(setup)/layout.tsx +++ b/src/app/(setup)/layout.tsx @@ -1,33 +1,23 @@ 'use client' -import { useAuth } from '@/context/authContext' import { usePWAStatus } from '@/hooks/usePWAStatus' import { useAppDispatch } from '@/redux/hooks' import { setupActions } from '@/redux/slices/setup-slice' -import { useRouter } from 'next/navigation' import { useEffect } from 'react' import { setupSteps } from '../../components/Setup/Setup.consts' import '../../styles/globals.bruddle.css' const SetupLayout = ({ children }: { children?: React.ReactNode }) => { - const { user } = useAuth() - const router = useRouter() const dispatch = useAppDispatch() const isPWA = usePWAStatus() useEffect(() => { - // if user is logged in, redirect to home - if (user) { - router.push('/home') - return - } - // filter steps and set them in redux state const filteredSteps = setupSteps.filter((step) => { return step.screenId !== 'pwa-install' || !isPWA }) dispatch(setupActions.setSteps(filteredSteps)) - }, [dispatch, isPWA, user]) + }, [dispatch, isPWA]) return <>{children} } diff --git a/src/components/Home/WalletCard.tsx b/src/components/Home/WalletCard.tsx index e5f0ea1f..b5e2b6d3 100644 --- a/src/components/Home/WalletCard.tsx +++ b/src/components/Home/WalletCard.tsx @@ -4,13 +4,13 @@ import { Card } from '@/components/0_Bruddle' import Icon from '@/components/Global/Icon' import { IWallet, WalletProviderType } from '@/interfaces' import { printableUsdc, shortenAddressLong } from '@/utils' +import { identicon } from '@dicebear/collection' +import { createAvatar } from '@dicebear/core' import classNames from 'classnames' import { motion } from 'framer-motion' import Image from 'next/image' import { useMemo } from 'react' import CopyToClipboard from '../Global/CopyToClipboard' -import { identicon } from '@dicebear/collection' -import { createAvatar } from '@dicebear/core' const colorArray = ['bg-blue-1', 'bg-yellow-1', 'bg-pink-1'] diff --git a/src/hooks/useWallet.ts b/src/hooks/useWallet.ts index 8fceef1c..473be2f9 100644 --- a/src/hooks/useWallet.ts +++ b/src/hooks/useWallet.ts @@ -9,7 +9,7 @@ import { useAppDispatch, useWalletStore } from '@/redux/hooks' import { walletActions } from '@/redux/slices/wallet-slice' import { areEvmAddressesEqual, backgroundColorFromAddress, fetchWalletBalances } from '@/utils' import { useQuery } from '@tanstack/react-query' -import { useCallback, useEffect, useMemo } from 'react' +import { useCallback, useEffect, useMemo, useRef } from 'react' import { erc20Abi, getAddress, parseUnits } from 'viem' import { useAccount } from 'wagmi' import { useZeroDev } from './useZeroDev' @@ -35,6 +35,9 @@ export const useWallet = () => { const { addAccount, user } = useAuth() const { selectedAddress, wallets, signInModalVisible, walletColor } = useWalletStore() + // use a ref to persist processed addresses across renders + const processedAddressesRef = useRef(new Set()) + const isWalletConnected = useCallback( (wallet: interfaces.IDBWallet): boolean => { if (isPeanut(wallet) && kernelClientAddress) { @@ -60,7 +63,10 @@ export const useWallet = () => { walletProviderType: account.account_type as unknown as interfaces.WalletProviderType, protocolType: interfaces.WalletProtocolType.EVM, address: account.account_identifier, - connector: account.connector, + connector: { + iconUrl: connector?.icon || account.connector?.iconUrl!, + name: connector?.name || account.connector?.name!, + }, } let balance = BigInt(0) @@ -93,11 +99,14 @@ export const useWallet = () => { connected: isWalletConnected(createDefaultDBWallet(address)), balances, balance: parseUnits(totalBalance.toString(), PEANUT_WALLET_TOKEN_DECIMALS), + connector: { + iconUrl: connector?.icon, + name: connector?.name, + }, } }) ) : [] - dispatch(walletActions.setWallets(processedWallets)) return processedWallets }, @@ -127,31 +136,45 @@ export const useWallet = () => { useEffect(() => { if (!user || !wagmiAddresses || !wallets.length) return - const newAddresses = wagmiAddresses.filter( - (addr) => !wallets.some((wallet) => areEvmAddressesEqual(addr, wallet.address)) - ) + // create a Set of existing wallet addresses for faster lookup + const existingAddresses = new Set(wallets.map((wallet) => wallet.address.toLowerCase())) + + // filter and process new addresses only once + const newAddresses = wagmiAddresses.filter((addr) => { + const lowerAddr = addr.toLowerCase() + if (!existingAddresses.has(lowerAddr) && !processedAddressesRef.current.has(lowerAddr)) { + processedAddressesRef.current.add(lowerAddr) + return true + } + return false + }) + if (newAddresses.length) { - newAddresses.forEach((address) => { - addAccount({ - accountIdentifier: address, - accountType: interfaces.WalletProviderType.BYOW, - userId: user.user.userId, - connector: - connector && connector.icon - ? { - iconUrl: connector.icon, - name: connector.name, - } - : undefined, - }).catch((error) => { - const errorMsg = error.message.includes('Account already exists') - ? 'Could not add external wallet, already associated with another account' - : 'Unexpected error adding external wallet' - toast.error(errorMsg) - }) + const connectorInfo = + connector && connector.icon + ? { + iconUrl: connector.icon, + name: connector.name, + } + : undefined + + Promise.all( + newAddresses.map((address) => + addAccount({ + accountIdentifier: address, + accountType: interfaces.WalletProviderType.BYOW, + userId: user.user.userId, + connector: connectorInfo, + }) + ) + ).catch((error) => { + const errorMsg = error.message.includes('Account already exists') + ? 'Could not add external wallet, already associated with another account' + : 'Unexpected error adding external wallet' + toast.error(errorMsg) }) } - }, [wagmiAddresses, wallets, user, addAccount, toast]) + }, [wagmiAddresses, user, wallets, connector]) const refetchBalances = useCallback( async (address: string) => { diff --git a/src/redux/store.ts b/src/redux/store.ts index 4a9ee7e0..1ca5404a 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -9,6 +9,11 @@ const store = configureStore({ wallet: walletReducer, zeroDev: zeroDevReducer, }, + // disable redux serialization checks + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: false, + }), }) export default store