Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "Your Wallet" page #480

Merged
Merged
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
118 changes: 92 additions & 26 deletions frontend/components/YourWalletPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import { CloseOutlined } from '@ant-design/icons';
import { Button, ConfigProvider, Flex, ThemeConfig, Typography } from 'antd';
import {
Button,
ConfigProvider,
Flex,
Skeleton,
ThemeConfig,
Typography,
} from 'antd';
import { isEmpty, isNil } from 'lodash';
import { useMemo } from 'react';

import { AddressLink } from '@/components/AddressLink';
import { CardTitle } from '@/components/Card/CardTitle';
import { InfoBreakdownList } from '@/components/InfoBreakdown';
import { CardFlex } from '@/components/styled/CardFlex';
import { getNativeTokenSymbol } from '@/config/tokens';
import { ChainId } from '@/enums/Chain';
import { Pages } from '@/enums/Pages';
import { useBalanceContext } from '@/hooks/useBalanceContext';
import { TokenSymbol } from '@/enums/Token';
import {
useBalanceContext,
useMasterBalances,
} from '@/hooks/useBalanceContext';
import { usePageState } from '@/hooks/usePageState';
import { useServices } from '@/hooks/useServices';
import { useWallet } from '@/hooks/useWallet';
import { useMasterWalletContext } from '@/hooks/useWallet';
import { type Address } from '@/types/Address';
import { Optional } from '@/types/Util';
import { balanceFormat } from '@/utils/numberFormatters';

import { Container, infoBreakdownParentStyle } from './styles';
Expand All @@ -25,10 +40,15 @@ const yourWalletTheme: ThemeConfig = {
},
};

const YourWalletTitle = () => <CardTitle title="Your wallet" />;
const YourWalletTitle = () => <CardTitle title="Your wallets" />;

const Address = () => {
const { masterSafeAddress } = useWallet();
const { masterSafes } = useMasterWalletContext();

if (!masterSafes) return <Skeleton />;
if (isEmpty(masterSafes)) return null;

const masterSafeAddress = masterSafes[0].address; // TODO: handle multiple safes in future

return (
<Flex vertical gap={8}>
Expand All @@ -48,47 +68,76 @@ const Address = () => {
};

const OlasBalance = () => {
const { masterSafeBalance: safeBalance, totalOlasStakedBalance } =
useBalanceContext();
const { masterSafes } = useMasterWalletContext();
const { walletBalances, totalStakedOlasBalance } = useBalanceContext();

const masterSafeOlasBalance: number = walletBalances
?.filter((balance) => balance.symbol === TokenSymbol.OLAS)
.reduce((acc, balance) => acc + balance.balance, 0);

const olasBalances = useMemo(() => {
return [
{
title: 'Available',
value: balanceFormat(safeBalance?.OLAS ?? 0, 2),
value: balanceFormat(masterSafeOlasBalance ?? 0, 2),
},
{
title: 'Staked',
value: balanceFormat(totalOlasStakedBalance ?? 0, 2),
value: balanceFormat(totalStakedOlasBalance ?? 0, 2),
},
];
}, [safeBalance?.OLAS, totalOlasStakedBalance]);
}, [masterSafeOlasBalance, totalStakedOlasBalance]);

if (!masterSafes) return <Skeleton />;
if (isEmpty(masterSafes)) return null;

return (
<Flex vertical gap={8}>
<Text strong>OLAS</Text>
<Text strong>{TokenSymbol.OLAS}</Text>
<InfoBreakdownList
list={olasBalances.map((item) => ({
left: item.title,
leftClassName: 'text-light',
right: `${item.value} OLAS`,
right: `${item.value} ${TokenSymbol.OLAS}`,
}))}
parentStyle={infoBreakdownParentStyle}
/>
</Flex>
);
};

const XdaiBalance = () => {
const { masterSafeBalance: safeBalance } = useBalanceContext();
const MasterSafeNativeBalance = () => {
const { masterSafes, masterEoa } = useMasterWalletContext();
const { masterWalletBalances } = useMasterBalances();

const masterSafeNativeBalance: Optional<number> = useMemo(() => {
if (isNil(masterSafes)) return;
if (isNil(masterWalletBalances)) return;

if (isEmpty(masterSafes)) return 0;
if (isEmpty(masterWalletBalances)) return 0;

const masterSafe = masterSafes[0]; // TODO: handle multiple safes in future

return masterWalletBalances
.filter(
({ walletAddress }) =>
walletAddress === masterSafe.address || // TODO: handle multiple safes in future
walletAddress === masterEoa?.address,
)
.reduce((acc, balance) => acc + balance.balance, 0);
}, [masterEoa?.address, masterSafes, masterWalletBalances]);

const nativeTokenSymbol = getNativeTokenSymbol(ChainId.Gnosis);

return (
<Flex vertical gap={8}>
<InfoBreakdownList
list={[
{
left: <Text strong>XDAI</Text>,
left: <Text strong>{getNativeTokenSymbol(ChainId.Gnosis)}</Text>,
leftClassName: 'text-light',
right: `${balanceFormat(safeBalance?.ETH, 2)} XDAI`,
right: `${balanceFormat(masterSafeNativeBalance, 2)} ${nativeTokenSymbol}`,
},
]}
parentStyle={infoBreakdownParentStyle}
Expand All @@ -97,9 +146,27 @@ const XdaiBalance = () => {
);
};

const Signer = () => {
const { masterEoaAddress } = useWallet();
const { masterEoaBalance: eoaBalance } = useBalanceContext();
const MasterEoaSignerNativeBalance = () => {
const { masterEoa } = useMasterWalletContext();
const { masterWalletBalances } = useMasterBalances();

const masterEoaBalance: Optional<number> = useMemo(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

here as well, can use useMasterBalances? and why not if not

Copy link
Collaborator

Choose a reason for hiding this comment

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

Balances and wallets require extra attention to fully understand 🙈

if (isNil(masterEoa)) return;
if (isNil(masterWalletBalances)) return;

return masterWalletBalances
.filter(
(
{ walletAddress, isNative }, // TODO: support chainId grouping, for multi-agent
) => walletAddress === masterEoa.address && isNative,
)
.reduce((acc, balance) => acc + balance.balance, 0);
}, [masterEoa, masterWalletBalances]);

const nativeTokenSymbol = useMemo(
() => getNativeTokenSymbol(ChainId.Gnosis),
[],
); // TODO: support multi chain

return (
<Flex vertical gap={8}>
Expand All @@ -109,11 +176,11 @@ const Signer = () => {
left: (
<SignerTitle
signerText="Your wallet signer address:"
signerAddress={masterEoaAddress}
signerAddress={masterEoa?.address}
/>
),
leftClassName: 'text-light',
right: `${balanceFormat(eoaBalance?.ETH, 2)} XDAI`,
right: `${balanceFormat(masterEoaBalance, 2)} ${nativeTokenSymbol}`,
},
]}
parentStyle={infoBreakdownParentStyle}
Expand All @@ -124,7 +191,6 @@ const Signer = () => {

export const YourWalletPage = () => {
const { goto } = usePageState();
const { service } = useServices();

return (
<ConfigProvider theme={yourWalletTheme}>
Expand All @@ -142,9 +208,9 @@ export const YourWalletPage = () => {
<Container style={{ margin: 8 }}>
<Address />
<OlasBalance />
<XdaiBalance />
<Signer />
{service && <YourAgentWallet />}
<MasterSafeNativeBalance />
<MasterEoaSignerNativeBalance />
<YourAgentWallet />
</Container>
</CardFlex>
</ConfigProvider>
Expand Down
Loading