Skip to content

Commit c69e5e3

Browse files
fix(balances): use live balances on the Portfolio screen
1 parent 8834920 commit c69e5e3

File tree

13 files changed

+348
-187
lines changed

13 files changed

+348
-187
lines changed

apps/next/src/pages/AccountManagement/AccountManagement.tsx

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,40 @@
1-
import {
2-
AccountManagerProvider,
3-
BalancesProvider,
4-
WalletTotalBalanceProvider,
5-
} from '@core/ui';
1+
import { AccountManagerProvider, WalletTotalBalanceProvider } from '@core/ui';
62
import { FC } from 'react';
73
import { Route, Switch, useRouteMatch } from 'react-router-dom';
84
import { AccountDetails } from './components/AccountDetails';
95
import { AddOrConnectWallet } from './components/AddOrCreateWallet/AddOrConnectWallet';
106
import { DeleteAccount } from './components/DeleteAccount';
7+
import { ImportKeystoreFile } from './components/ImportKeystoreFile/Page';
118
import { ImportPrivateKey } from './components/ImportPrivateKey/Page';
129
import { QRCode } from './components/QRCode';
1310
import { RenamePage } from './components/RenamePage';
1411
import { ShowPrivateKey } from './components/ShowPrivateKey/ShowPrivateKey';
1512
import { WalletsHomePage } from './components/Wallets';
16-
import { ImportKeystoreFile } from './components/ImportKeystoreFile/Page';
1713

1814
const AccountManagement: FC = () => {
1915
const { path } = useRouteMatch();
2016
return (
21-
<BalancesProvider>
22-
<WalletTotalBalanceProvider>
23-
<AccountManagerProvider>
24-
<Switch>
25-
<Route path={path} exact component={WalletsHomePage} />
26-
<Route path={`${path}/rename`} component={RenamePage} />
27-
<Route path={`${path}/delete-account`} component={DeleteAccount} />
28-
<Route path={`${path}/qr-code`} component={QRCode} />
29-
<Route path={`${path}/add-wallet`} component={AddOrConnectWallet} />
30-
<Route
31-
path={`${path}/import-private-key`}
32-
component={ImportPrivateKey}
33-
/>
34-
<Route
35-
path={`${path}/import-keystore-file`}
36-
component={ImportKeystoreFile}
37-
/>
38-
<Route path={`${path}/account`} component={AccountDetails} />
39-
<Route
40-
path={`${path}/show-private-key`}
41-
component={ShowPrivateKey}
42-
/>
43-
</Switch>
44-
</AccountManagerProvider>
45-
</WalletTotalBalanceProvider>
46-
</BalancesProvider>
17+
<WalletTotalBalanceProvider>
18+
<AccountManagerProvider>
19+
<Switch>
20+
<Route path={path} exact component={WalletsHomePage} />
21+
<Route path={`${path}/rename`} component={RenamePage} />
22+
<Route path={`${path}/delete-account`} component={DeleteAccount} />
23+
<Route path={`${path}/qr-code`} component={QRCode} />
24+
<Route path={`${path}/add-wallet`} component={AddOrConnectWallet} />
25+
<Route
26+
path={`${path}/import-private-key`}
27+
component={ImportPrivateKey}
28+
/>
29+
<Route
30+
path={`${path}/import-keystore-file`}
31+
component={ImportKeystoreFile}
32+
/>
33+
<Route path={`${path}/account`} component={AccountDetails} />
34+
<Route path={`${path}/show-private-key`} component={ShowPrivateKey} />
35+
</Switch>
36+
</AccountManagerProvider>
37+
</WalletTotalBalanceProvider>
4738
);
4839
};
4940

apps/next/src/pages/AccountManagement/components/Wallets/components/AccountListItem/components/AccountBalance.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { Stack, Tooltip, Typography } from '@avalabs/k2-alpine';
22
import { Account } from '@core/types';
33

4-
import { useBalancesContext } from '@core/ui/src/contexts/BalancesProvider';
5-
import { useSettingsContext } from '@core/ui/src/contexts/SettingsProvider';
6-
import { useBalanceTotalInCurrency } from '@core/ui/src/hooks/useBalanceTotalInCurrency';
4+
import {
5+
useBalancesContext,
6+
useBalanceTotalInCurrency,
7+
useSettingsContext,
8+
} from '@core/ui';
79
import { FC } from 'react';
810
import { useTranslation } from 'react-i18next';
911
import * as Styled from '../../Styled';

apps/next/src/pages/Portfolio/components/PortfolioHome/PortfolioHome.tsx

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
1-
import {
2-
CircularProgress,
3-
Stack,
4-
styled,
5-
TabBar,
6-
TabBarItemProps,
7-
} from '@avalabs/k2-alpine';
8-
import { hasAccountBalances } from '@core/common';
1+
import { NoScrollStack } from '@/components/NoScrollStack';
2+
import { Stack, TabBar, TabBarItemProps } from '@avalabs/k2-alpine';
3+
import { isEmptyAccount } from '@core/common';
94
import {
105
useAccountsContext,
116
useBalancesContext,
127
useNetworkContext,
138
} from '@core/ui';
149
import { FC, useState } from 'react';
15-
import { NoScrollStack } from '@/components/NoScrollStack';
1610

11+
import { TestnetModeOverlay } from '@/components/TestnetModeOverlay';
12+
import { TESTNET_MODE_BACKGROUND_COLOR } from '@/config/constants';
13+
import { useTranslation } from 'react-i18next';
14+
import { useHistory, useLocation } from 'react-router-dom';
1715
import AccountInfo from './components/AccountInfo';
1816
import { EmptyState } from './components/EmptyState';
17+
import { LoadingState } from './components/LoadingState';
1918
import { PortfolioDetails } from './components/PortolioDetails';
20-
import { useTranslation } from 'react-i18next';
21-
import { TESTNET_MODE_BACKGROUND_COLOR } from '@/config/constants';
22-
import { TestnetModeOverlay } from '@/components/TestnetModeOverlay';
23-
import { useHistory, useLocation } from 'react-router-dom';
2419
import { TabsContainer } from './styled';
2520

26-
export type TabName = 'assets' | 'collectibles' | 'defi' | 'activity';
21+
import { TabName } from './types';
2722

2823
export const PortfolioHome: FC = () => {
2924
const { t } = useTranslation();
@@ -42,13 +37,10 @@ export const PortfolioHome: FC = () => {
4237
);
4338
const { networks, isDeveloperMode } = useNetworkContext();
4439
const { totalBalance, balances } = useBalancesContext();
45-
const isLoading = !totalBalance;
40+
41+
const isLoading = balances.loading || !totalBalance;
4642
const isAccountEmpty =
47-
!hasAccountBalances(
48-
balances.tokens ?? {},
49-
accounts.active ?? {},
50-
networks.map((n) => n.chainId),
51-
) && !isLoading;
43+
!isLoading && isEmptyAccount(balances.tokens, accounts.active, networks);
5244

5345
const TABS: TabBarItemProps[] = [
5446
{
@@ -92,7 +84,7 @@ export const PortfolioHome: FC = () => {
9284
/>
9385
<Stack flexGrow={1} gap={2.5}>
9486
{isLoading ? (
95-
<CenteredSpinner />
87+
<LoadingState />
9688
) : (
9789
<PortfolioContent tab={activeTab} />
9890
)}
@@ -123,7 +115,3 @@ export const PortfolioHome: FC = () => {
123115
</>
124116
);
125117
};
126-
127-
const CenteredSpinner = styled(CircularProgress)({
128-
margin: 'auto',
129-
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Box, Skeleton, Stack } from '@avalabs/k2-alpine';
2+
import { FC } from 'react';
3+
4+
export const LoadingState: FC = () => {
5+
return (
6+
<Stack gap={1.25} height={1} overflow="clip">
7+
<ActionButtonsSkeleton />
8+
<TrendingTokensSkeleton />
9+
<FiltersBarSkeleton />
10+
<TokensListSkeleton />
11+
</Stack>
12+
);
13+
};
14+
15+
const ActionButtonsSkeleton: FC = () => {
16+
return (
17+
<Stack direction="row" gap={1}>
18+
<Skeleton height={60} width={60} animation="wave" variant="rounded" />
19+
<Skeleton height={60} width={60} animation="wave" variant="rounded" />
20+
<Skeleton height={60} width={60} animation="wave" variant="rounded" />
21+
<Skeleton height={60} width={60} animation="wave" variant="rounded" />
22+
</Stack>
23+
);
24+
};
25+
26+
const TrendingTokensSkeleton: FC = () => {
27+
return (
28+
<Box pt={1.25}>
29+
<Skeleton height={40} animation="wave" variant="rounded" />
30+
</Box>
31+
);
32+
};
33+
34+
const FiltersBarSkeleton: FC = () => {
35+
return (
36+
<Stack direction="row" justifyContent="space-between">
37+
<Stack direction="row" gap={1}>
38+
<Skeleton width={65} height={24} animation="wave" variant="rounded" />
39+
<Skeleton width={62} height={24} animation="wave" variant="rounded" />
40+
</Stack>
41+
<Skeleton width={70} height={24} animation="wave" variant="rounded" />
42+
</Stack>
43+
);
44+
};
45+
46+
const TokensListSkeleton: FC = () => {
47+
return (
48+
<Stack gap={1}>
49+
<Skeleton width="100%" height={50} animation="wave" variant="rounded" />
50+
<Skeleton width="100%" height={50} animation="wave" variant="rounded" />
51+
<Skeleton width="100%" height={50} animation="wave" variant="rounded" />
52+
</Stack>
53+
);
54+
};

apps/next/src/pages/Portfolio/components/PortfolioHome/components/PortolioDetails/PortfolioDetails.tsx

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
1-
import { FC } from 'react';
1+
import { TokenType } from '@avalabs/vm-module-types';
2+
import { useLiveBalance } from '@core/ui';
3+
import { ComponentType, FC } from 'react';
4+
import { TabName } from '../../types';
25
import { ActivityTab, AssetsTab, CollectiblesTab, DeFiTab } from './components';
36
import { PortfolioActionButtons } from './components/PortfolioActionButtons';
4-
import { TabName } from '../../PortfolioHome';
57

68
type Props = {
79
tab: TabName;
810
};
911

10-
const tabComponents: Record<TabName, FC> = {
11-
assets: AssetsTab,
12-
collectibles: CollectiblesTab,
13-
defi: DeFiTab,
14-
activity: ActivityTab,
12+
type TabConfig = {
13+
TabComponent: ComponentType;
14+
balancesFor: TokenType[];
15+
};
16+
const tabConfig: Record<TabName, TabConfig> = {
17+
assets: {
18+
TabComponent: AssetsTab,
19+
balancesFor: [TokenType.NATIVE, TokenType.ERC20],
20+
},
21+
collectibles: {
22+
TabComponent: CollectiblesTab,
23+
balancesFor: [TokenType.ERC721, TokenType.ERC1155],
24+
},
25+
defi: { TabComponent: DeFiTab, balancesFor: [] },
26+
activity: { TabComponent: ActivityTab, balancesFor: [] },
1527
};
1628

1729
export const PortfolioDetails: FC<Props> = ({ tab }) => {
18-
const TabComponent = tabComponents[tab];
30+
const { TabComponent, balancesFor } = tabConfig[tab];
31+
useLiveBalance(balancesFor);
1932

2033
return (
2134
<>

apps/next/src/pages/Portfolio/components/PortfolioHome/components/PortolioDetails/components/CollectiblesTab/CollectiblesTab.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1+
import { Box, CircularProgress, Stack } from '@avalabs/k2-alpine';
2+
import { NftTokenWithBalance } from '@avalabs/vm-module-types';
3+
import { useAccountsContext, useNetworkContext, useNfts } from '@core/ui';
4+
import { isEmpty } from 'lodash';
15
import { useCallback, useMemo } from 'react';
2-
import { Stack, Box, CircularProgress } from '@avalabs/k2-alpine';
3-
import { CollectibleListEmpty } from './components/CollectibleListEmpty';
6+
import { useTranslation } from 'react-i18next';
47
import { CollectibleCard } from './components/CollectibleCard';
8+
import { CollectibleListEmpty } from './components/CollectibleListEmpty';
9+
import { CollectibleToolbar } from './components/CollectibleToolbar';
10+
import { CollectiblesManagePopup } from './components/CollectiblesManagePopup';
511
import { VirtualizedGrid } from './components/VirtualizedGrid';
6-
import { useAccountsContext, useNetworkContext, useNfts } from '@core/ui';
7-
import { useLiveBalance } from '@core/ui';
8-
import { NftTokenWithBalance, TokenType } from '@avalabs/vm-module-types';
912
import {
1013
FilterType,
1114
useCollectiblesToolbar,
1215
} from './hooks/useCollectiblesToolbar';
1316
import {
14-
getUniqueCollectibleId,
15-
getStaticMimeType,
1617
getCollectibleMediaType,
1718
getCoreCollectibleUrl,
19+
getStaticMimeType,
20+
getUniqueCollectibleId,
1821
} from './utils';
19-
import { CollectibleToolbar } from './components/CollectibleToolbar';
20-
import { CollectiblesManagePopup } from './components/CollectiblesManagePopup';
21-
import { useTranslation } from 'react-i18next';
22-
import { isEmpty } from 'lodash';
2322

2423
export type FormattedCollectible = NftTokenWithBalance & {
2524
collectibleTypeMedia: FilterType;
@@ -29,11 +28,7 @@ export type FormattedCollectible = NftTokenWithBalance & {
2928
coreCollectibleUrl?: string;
3029
};
3130

32-
const POLLED_BALANCES = [TokenType.ERC721, TokenType.ERC1155];
33-
3431
export function CollectiblesTab() {
35-
useLiveBalance(POLLED_BALANCES);
36-
3732
const { collectibles, loading } = useNfts();
3833
const { t } = useTranslation();
3934
const { isDeveloperMode } = useNetworkContext();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type TabName = 'assets' | 'collectibles' | 'defi' | 'activity';

apps/next/src/popup/app.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ const pagesWithoutHeader = [
6565
'/asset', // Token details path
6666
];
6767

68-
// Create a client for React Query
6968
const queryClient = new QueryClient({
7069
defaultOptions: {
7170
queries: {

packages/common/src/utils/hasAccountBalances.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { ChainId, NetworkToken } from '@avalabs/core-chains-sdk';
2+
import { NetworkTokenWithBalance, TokenType } from '@avalabs/vm-module-types';
23
import { Account, AccountType, Balances } from '@core/types';
34
import { hasAccountBalances } from './hasAccountBalances';
4-
import { NetworkTokenWithBalance, TokenType } from '@avalabs/vm-module-types';
55

6-
describe('utils/calculateTotalBalance', () => {
6+
describe('utils/hasAccountBalances', () => {
77
const account1: Account = {
88
id: 'account1 ID',
99
name: 'account1 name',

0 commit comments

Comments
 (0)