Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
150 changes: 79 additions & 71 deletions src/app/(mobile-ui)/wallet/page.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
'use client'

import { ARBITRUM_ICON } from '@/assets'
import { Button } from '@/components/0_Bruddle'
import DirectionalActionButtons from '@/components/Global/DirectionalActionButtons'
import NoDataEmptyState from '@/components/Global/EmptyStates/NoDataEmptyState'
import Icon from '@/components/Global/Icon'
import { ListItemView } from '@/components/Global/ListItemView'
import NavHeader from '@/components/Global/NavHeader'
import { WalletCard } from '@/components/Home/WalletCard'
import { PEANUT_WALLET_CHAIN, PEANUT_WALLET_TOKEN_DECIMALS, PEANUT_WALLET_TOKEN_NAME } from '@/constants'
import { useAuth } from '@/context/authContext'
import { useWallet } from '@/hooks/wallet/useWallet'
import { IUserBalance } from '@/interfaces'
import { useWalletConnection } from '@/hooks/wallet/useWalletConnection'
import { IWallet, WalletProviderType } from '@/interfaces'
import { useWalletStore } from '@/redux/hooks'
import { formatAmount, getChainName, getHeaderTitle, getUserPreferences, updateUserPreferences } from '@/utils'
import { useAppKit, useDisconnect } from '@reown/appkit/react'
import { useDisconnect } from '@reown/appkit/react'
import { usePathname } from 'next/navigation'
import { useMemo, useState } from 'react'
import { twMerge } from 'tailwind-merge'
import { useState } from 'react'
import { formatUnits } from 'viem'

const WalletDetailsPage = () => {
const pathname = usePathname()
const { open } = useAppKit()
const { disconnect } = useDisconnect()
const { focusedWallet, wallets } = useWalletStore()
const { isConnected, address } = useWallet()
const { focusedWallet } = useWalletStore()
const { connectWallet } = useWalletConnection()
const { isWalletConnected, wallets } = useWallet()
const { username } = useAuth()
const [isBalanceHidden, setIsBalanceHidden] = useState(() => {
const prefs = getUserPreferences()
return prefs?.balanceHidden ?? false
})

const walletDetails = useMemo(
() => wallets.find((wallet) => wallet.address === focusedWallet),
[focusedWallet, wallets]
)
const walletDetails = wallets.find((wallet) => wallet.address === focusedWallet)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: why wallet.address is the id in this case? accountId from BE would be better imo. Then again we also have accountIdentifier in Backend, so address works kinda too. But the var names should be renamed if we add banking accounts to selectable accounts

const isPeanutWallet = walletDetails?.walletProviderType === WalletProviderType.PEANUT
const isConnected = isWalletConnected(walletDetails as IWallet)

const handleToggleBalanceVisibility = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
Expand All @@ -43,6 +45,62 @@ const WalletDetailsPage = () => {
})
}

const renderTokenDetails = () => {
if (!walletDetails) return null
if (isPeanutWallet) {
return walletDetails.balance && Number(walletDetails.balance) > 0 ? (
<div className="space-y-3">
<div className="text-base font-semibold">Balance</div>
<div className="border border-b-black">
<ListItemView
key={`peanut-${walletDetails.address}`}
id={`${PEANUT_WALLET_CHAIN.id}-${PEANUT_WALLET_CHAIN.name}`}
variant="balance"
primaryInfo={{ title: PEANUT_WALLET_TOKEN_NAME }}
secondaryInfo={{
mainText: `$ ${formatAmount(formatUnits(walletDetails.balance, PEANUT_WALLET_TOKEN_DECIMALS))}`,
subText: PEANUT_WALLET_CHAIN.name,
}}
metadata={{
tokenLogo: ARBITRUM_ICON,
subText: `${formatAmount(formatUnits(walletDetails.balance, PEANUT_WALLET_TOKEN_DECIMALS))} USDC`,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I still hate formatAmount(formatUnits)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

formatformatformat

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ouch, this one can be fixed, my baddd, mee dummbbb

}}
/>
</div>
</div>
) : (
<NoDataEmptyState message="You don't have funds in your Peanut wallet" />
)
} else {
return walletDetails.balances?.length ? (
<div className="space-y-3 border-b border-b-black">
<div className="text-base font-semibold">Balance</div>
<div>
{walletDetails.balances.map((balance) => (
<ListItemView
key={`${balance.chainId}-${balance.symbol}`}
id={`${balance.chainId}-${balance.symbol}`}
variant="balance"
primaryInfo={{ title: balance.symbol }}
secondaryInfo={{
mainText: `$ ${Number(balance.value).toFixed(2)}`,
subText: getChainName(balance.chainId),
}}
metadata={{
tokenLogo: balance.logoURI,
subText: `${formatAmount(balance.amount)} ${balance.symbol}`,
}}
details={balance}
/>
))}
</div>
</div>
) : (
<NoDataEmptyState message="No tokens found" />
)
}
}

return (
<div className="mx-auto flex w-full flex-col gap-6 md:max-w-2xl">
<div className="md:hidden">
Expand All @@ -59,80 +117,30 @@ const WalletDetailsPage = () => {
selected
onClick={() => {}}
index={0}
isFocused
isBalanceHidden={isBalanceHidden}
onToggleBalanceVisibility={handleToggleBalanceVisibility}
/>
)}
</div>

<DirectionalActionButtons
leftButton={{
title: 'Top up',
href: '/topup',
disabled: true,
}}
rightButton={{
title: 'Cash out',
href: '/cashout',
}}
leftButton={{ title: 'Top up', href: '/topup', disabled: true }}
rightButton={{ title: 'Cashout', href: '/cashout' }}
/>

<div
className={twMerge(
walletDetails?.balances && !!walletDetails?.balances?.length ? 'border-b border-b-n-1' : ''
)}
>
{!!walletDetails?.balances?.length ? (
<div className="space-y-3">
<div className="text-base font-semibold">Balance</div>
<div>
{walletDetails.balances.map((balance: IUserBalance) => (
<ListItemView
key={`${balance.chainId}-${balance.symbol}`}
id={`${balance.chainId}-${balance.symbol}`}
variant="balance"
primaryInfo={{
title: balance.symbol,
}}
secondaryInfo={{
mainText: `$${Number(balance.value).toFixed(2)}`,
subText: getChainName(balance.chainId),
}}
metadata={{
tokenLogo: balance.logoURI,
subText: `${formatAmount(balance.amount)} ${balance.symbol}`,
}}
details={balance}
/>
))}
</div>
</div>
) : (
<NoDataEmptyState message="No tokens found" />
)}
</div>
<div>
{renderTokenDetails()}

{!isPeanutWallet && (
<Button
onClick={() => {
if (isConnected && walletDetails?.address === address) {
disconnect()
} else {
open()
}
}}
onClick={() => (isConnected ? disconnect() : connectWallet())}
variant="transparent-light"
className="flex w-full items-center justify-center gap-2 border border-black bg-purple-5 hover:bg-purple-5"
>
<Icon
name={isConnected && walletDetails?.address === address ? 'minus-circle' : 'plus-circle'}
fill="black"
className="size-4"
/>
<div className="text-black">
{isConnected && walletDetails?.address === address ? 'Disconnect' : 'Connect'}
</div>
<Icon name={isConnected ? 'minus-circle' : 'plus-circle'} fill="black" className="size-4" />
<div className="text-black">{isConnected ? 'Disconnect Wallet' : 'Connect Wallet'}</div>
</Button>
</div>
)}
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Global/ListItemView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ interface ListItemViewProps {
recipientAddress?: string
transactionType?: TransactionType
}
details: IDashboardItem | TokenBalance
details?: IDashboardItem | TokenBalance
}

const getTransactionStatus = (type: TransactionType | undefined, status: string | undefined): string => {
Expand Down
5 changes: 3 additions & 2 deletions src/constants/zerodev.consts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { arbitrum } from 'viem/chains'
import { getEntryPoint } from '@zerodev/sdk/constants'
import { arbitrum } from 'viem/chains'

// consts needed to define low level SDK kernel
// as per: https://docs.zerodev.app/sdk/getting-started/tutorial-passkeys
Expand All @@ -13,7 +13,8 @@ export const ZERO_DEV_PROJECT_ID = process.env.NEXT_PUBLIC_ZERO_DEV_PASSKEY_PROJ

export const PEANUT_WALLET_CHAIN = arbitrum
//USDC Arbitrum address
export const PEANUT_WALLET_TOKEN_DECIMALS = 6 // USDC decimals
export const PEANUT_WALLET_TOKEN = '0xaf88d065e77c8cc2239327c5edb3a432268e5831'
export const PEANUT_WALLET_TOKEN_DECIMALS = 6 //USDC decimals
export const PEANUT_WALLET_TOKEN_NAME = 'USDC'

export const USER_OP_ENTRY_POINT = getEntryPoint('0.7')