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
65 changes: 54 additions & 11 deletions apps/app/app/content.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
'use client'

import {Box, Divider, Grid, Stack, Typography} from '@mui/material'
import {toCurrency} from '@phala/lib'
import phaIcon from '@phala/ui/icons/asset/pha.png'
import vphaIcon from '@phala/ui/icons/asset/vpha.png'
import {useAppKitAccount, useAppKitNetwork} from '@reown/appkit/react'
import Decimal from 'decimal.js'
import {useMemo} from 'react'
import {useCallback, useMemo} from 'react'
import {erc20Abi, formatUnits} from 'viem'
import {mainnet} from 'viem/chains'
import {useReadContract} from 'wagmi'
Expand All @@ -20,6 +21,7 @@ import {
VAULT_CONTRACT_ADDRESS,
} from '@/config'
import {useRewardRate, useSharePrice, useTotalAssets} from '@/hooks/staking'
import {useAddTokenToWallet} from '@/hooks/use-add-token-to-wallet'
import {phalaNetwork, toAddress} from '@/lib/wagmi'

export default function HomeContent() {
Expand All @@ -29,6 +31,7 @@ export default function HomeContent() {
const sharePrice = useSharePrice()
const totalAssets = useTotalAssets()
const rewardRate = useRewardRate()
const {addTokenToWallet, addNetwork} = useAddTokenToWallet()

const isValidConnection = isConnected && chainId === ethChain.id

Expand Down Expand Up @@ -79,12 +82,16 @@ export default function HomeContent() {

const l1VphaInPha = useMemo(() => {
if (l1VphaBalance == null || sharePrice == null) return null
return (l1VphaBalance * sharePrice) / BigInt(1e18)
return new Decimal(formatUnits(l1VphaBalance, 18)).mul(
formatUnits(sharePrice, 18),
)
}, [l1VphaBalance, sharePrice])

const l2VphaInPha = useMemo(() => {
if (l2VphaBalance == null || sharePrice == null) return null
return (l2VphaBalance * sharePrice) / BigInt(1e18)
return new Decimal(formatUnits(l2VphaBalance, 18)).mul(
formatUnits(sharePrice, 18),
)
}, [l2VphaBalance, sharePrice])

const totalVphaBalance = useMemo(() => {
Expand All @@ -94,16 +101,47 @@ export default function HomeContent() {

const totalVphaInPha = useMemo(() => {
if (l1VphaInPha == null && l2VphaInPha == null) return null
return (l1VphaInPha ?? 0n) + (l2VphaInPha ?? 0n)
return (l1VphaInPha ?? new Decimal(0)).add(l2VphaInPha ?? new Decimal(0))
}, [l1VphaInPha, l2VphaInPha])

const totalPhaValue = useMemo(() => {
if (!isValidConnection) return null
const pha = l1PhaBalance ?? 0n
const vpha = totalVphaInPha ?? 0n
return pha + vpha
const pha = new Decimal(formatUnits(l1PhaBalance ?? 0n, 18))
const vpha = totalVphaInPha ?? new Decimal(0)
return pha.add(vpha)
}, [isValidConnection, l1PhaBalance, totalVphaInPha])

const addPhaToWallet = useCallback(() => {
addTokenToWallet({
chainId: mainnet.id,
address: PHA_CONTRACT_ADDRESS,
symbol: 'PHA',
image: 'https://app.phala.network/icons/pha.png',
})
}, [addTokenToWallet])

const addL1VphaToWallet = useCallback(() => {
addTokenToWallet({
chainId: mainnet.id,
address: VAULT_CONTRACT_ADDRESS,
symbol: 'vPHA',
image: 'https://app.phala.network/icons/vpha.png',
})
}, [addTokenToWallet])

const addL2VphaToWallet = useCallback(() => {
addTokenToWallet({
chainId: phalaNetwork.id,
address: L2_VPHA_CONTRACT_ADDRESS,
symbol: 'vPHA',
image: 'https://app.phala.network/icons/vpha.png',
})
}, [addTokenToWallet])

const addPhalaNetworkToWallet = useCallback(() => {
addNetwork(phalaNetwork.id)
}, [addNetwork])

return (
<Box pb={10} pt={3}>
<Stack spacing={4}>
Expand Down Expand Up @@ -134,6 +172,7 @@ export default function HomeContent() {
contractAddress={PHA_CONTRACT_ADDRESS}
chainLabel="Ethereum"
highlight
onAddToWallet={addPhaToWallet}
actions={[
{
label: 'Stake',
Expand Down Expand Up @@ -164,13 +203,14 @@ export default function HomeContent() {
chainLabel="Ethereum"
subValue={
isValidConnection && l1VphaInPha != null
? `≈ ${formatUnits(l1VphaInPha, 18).slice(0, 12)} PHA`
? `≈ ${toCurrency(l1VphaInPha)} PHA`
: undefined
}
onAddToWallet={addL1VphaToWallet}
actions={[
{
label: 'Unstake',
href: '/staking',
href: '/staking?tab=unstake',
variant: 'outlined',
},
{
Expand All @@ -190,12 +230,15 @@ export default function HomeContent() {
balance={isValidConnection ? l2VphaBalance : null}
contractAddress={L2_VPHA_CONTRACT_ADDRESS}
contractExplorerUrl="https://explorer.phala.network"
chainLabel="Phala L2"
chainLabel="Phala Mainnet"
subValue={
isValidConnection && l2VphaInPha != null
? `≈ ${formatUnits(l2VphaInPha, 18).slice(0, 12)} PHA`
? `≈ ${toCurrency(l2VphaInPha)} PHA`
: undefined
}
onAddToWallet={addL2VphaToWallet}
addToWalletLabel="Add vPHA"
onAddNetwork={addPhalaNetworkToWallet}
actions={[
{
label: 'Bridge to L1',
Expand Down
8 changes: 4 additions & 4 deletions apps/app/app/khala-assets/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function KhalaAssetsContent() {
target="_blank"
rel="noopener noreferrer"
>
Phala L2
Phala Mainnet
</Link>
, our new Ethereum Layer 2 network.
</Typography>
Expand Down Expand Up @@ -134,7 +134,7 @@ export default function KhalaAssetsContent() {
</Link>
</Typography>
<Typography variant="subtitle1" fontWeight={500} sx={{mt: 2}}>
How to transfer vPHA between Ethereum and Phala L2?
How to transfer vPHA between Ethereum and Phala Mainnet?
</Typography>
<Typography variant="body2" color="text.secondary">
You can use{' '}
Expand All @@ -145,8 +145,8 @@ export default function KhalaAssetsContent() {
>
Phala Bridge
</Link>{' '}
to transfer vPHA tokens between Ethereum (L1) and Phala L2. The
bridge supports bidirectional transfers, allowing you to move
to transfer vPHA tokens between Ethereum (L1) and Phala Mainnet.
The bridge supports bidirectional transfers, allowing you to move
assets freely between both networks.
</Typography>
</Stack>
Expand Down
55 changes: 29 additions & 26 deletions apps/app/app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {QueryCache, QueryClient} from '@tanstack/react-query'
import {ReactQueryDevtools} from '@tanstack/react-query-devtools'
import Decimal from 'decimal.js'
import {Provider as JotaiProvider} from 'jotai'
import {NuqsAdapter} from 'nuqs/adapters/next/app'
import type {ReactNode} from 'react'
import {useState} from 'react'
import {SWRConfig} from 'swr'
Expand Down Expand Up @@ -46,32 +47,34 @@ export default function Providers({
)

return (
<SWRConfig
value={{
onError: (error, key) => {
if (process.env.NODE_ENV === 'development') {
console.error(key, error)
}
},
}}
>
<JotaiProvider>
<AppRouterCacheProvider>
<MuiThemeProvider theme={theme}>
<Web3Provider queryClient={queryClient} cookies={cookies}>
<CssBaseline />
<GlobalStyles styles={[globalStyles]} />
<NuqsAdapter>
<SWRConfig
value={{
onError: (error, key) => {
if (process.env.NODE_ENV === 'development') {
console.error(key, error)
}
},
}}
>
<JotaiProvider>
<AppRouterCacheProvider>
<MuiThemeProvider theme={theme}>
<Web3Provider queryClient={queryClient} cookies={cookies}>
<CssBaseline />
<GlobalStyles styles={[globalStyles]} />

<SnackbarProvider>
<Layout>
{children}
<ReactQueryDevtools buttonPosition="bottom-left" />
</Layout>
</SnackbarProvider>
</Web3Provider>
</MuiThemeProvider>
</AppRouterCacheProvider>
</JotaiProvider>
</SWRConfig>
<SnackbarProvider>
<Layout>
{children}
<ReactQueryDevtools buttonPosition="bottom-left" />
</Layout>
</SnackbarProvider>
</Web3Provider>
</MuiThemeProvider>
</AppRouterCacheProvider>
</JotaiProvider>
</SWRConfig>
</NuqsAdapter>
)
}
81 changes: 45 additions & 36 deletions apps/app/components/asset-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {FC, ReactNode} from 'react'
import {formatUnits} from 'viem'

import {explorerUrl} from '@/config'
import MetaMaskButton from './metamask-button'

export interface AssetAction {
label: string
Expand All @@ -37,6 +38,9 @@ interface AssetCardProps {
subValue?: ReactNode
actions?: AssetAction[]
highlight?: boolean
onAddToWallet?: () => void
addToWalletLabel?: string
onAddNetwork?: () => void
}

const AssetCard: FC<AssetCardProps> = ({
Expand All @@ -50,6 +54,9 @@ const AssetCard: FC<AssetCardProps> = ({
subValue,
actions = [],
highlight = false,
onAddToWallet,
addToWalletLabel,
onAddNetwork,
}) => {
const tokenExplorerUrl = contractExplorerUrl
? `${contractExplorerUrl}/token/${contractAddress}`
Expand Down Expand Up @@ -163,42 +170,44 @@ const AssetCard: FC<AssetCardProps> = ({
</Box>
</Box>

{actions.length > 0 && (
<Stack
direction="row"
spacing={1}
flexWrap="wrap"
useFlexGap
mt="auto"
>
{actions.map((action) => (
<Button
key={action.label}
size="small"
variant={action.variant || 'outlined'}
disabled={action.disabled}
component={action.external ? 'a' : NextLink}
href={action.href}
target={action.external ? '_blank' : undefined}
rel={action.external ? 'noopener noreferrer' : undefined}
endIcon={
action.external ? (
<OpenInNew sx={{width: 14, height: 14}} />
) : (
<ArrowForward sx={{width: 14, height: 14}} />
)
}
sx={{
fontSize: '0.75rem',
py: 0.5,
px: 1.5,
}}
>
{action.label}
</Button>
))}
</Stack>
)}
<Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap mt="auto">
{actions.map((action) => (
<Button
key={action.label}
size="small"
variant={action.variant || 'outlined'}
disabled={action.disabled}
component={action.external ? 'a' : NextLink}
href={action.href}
target={action.external ? '_blank' : undefined}
rel={action.external ? 'noopener noreferrer' : undefined}
endIcon={
action.external ? (
<OpenInNew sx={{width: 14, height: 14}} />
) : (
<ArrowForward sx={{width: 14, height: 14}} />
)
}
sx={{
fontSize: '0.75rem',
py: 0.5,
px: 1.5,
}}
>
{action.label}
</Button>
))}
{onAddNetwork && (
<MetaMaskButton onClick={onAddNetwork}>
Add Phala Mainnet
</MetaMaskButton>
)}
{onAddToWallet && (
<MetaMaskButton onClick={onAddToWallet}>
{addToWalletLabel ?? `Add ${symbol}`}
</MetaMaskButton>
)}
</Stack>
</Stack>
</Paper>
)
Expand Down
42 changes: 42 additions & 0 deletions apps/app/components/chain-badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {Typography, type TypographyProps} from '@mui/material'
import type {FC} from 'react'

type ChainType = 'ethereum' | 'phala'

interface ChainBadgeProps extends Omit<TypographyProps, 'variant' | 'sx'> {
chain: ChainType
}

const chainConfig: Record<ChainType, {label: string; color: string}> = {
ethereum: {
label: 'Ethereum',
color: 'primary.main',
},
phala: {
label: 'Phala Mainnet',
color: 'secondary.main',
},
}

const ChainBadge: FC<ChainBadgeProps> = ({chain, ...props}) => {
const config = chainConfig[chain]

return (
<Typography
variant="caption"
sx={{
border: 1,
borderColor: config.color,
color: config.color,
px: 1,
py: 0.25,
borderRadius: 1,
}}
{...props}
>
{config.label}
</Typography>
)
}

export default ChainBadge
Loading