Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
d545fd9
feat(wallet-switcher): initial update wallet switcher broken
frichards Nov 12, 2025
1ca8856
fix(wallet-view): fix route detecting bug
frichards Nov 12, 2025
4dd57b8
feat: wallet view navigation logic
frichards Nov 13, 2025
75263a5
fix: route flow and wallet switcher update
frichards Nov 13, 2025
3f493e5
feat(wallet-view): intro to PrimaryWallet
frichards Nov 14, 2025
734a314
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 14, 2025
62f0839
fix: revert wallet list changes since other ticket will handle this
frichards Nov 14, 2025
d9f3ede
fix: more reverting
frichards Nov 14, 2025
4ac648a
fix: another revert
frichards Nov 14, 2025
0ade433
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 14, 2025
46aad6f
fix: headerAccount styling update
frichards Nov 15, 2025
3ff7dcf
fix: wallet balance change and balanceChange component
frichards Nov 17, 2025
db5ce91
feat(wallet-view): wip WalletAccount
frichards Nov 17, 2025
5457fcc
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 17, 2025
1b9fe79
feat: wallet account styling and data
frichards Nov 18, 2025
d320c6a
fix(avatar): assign random avatar for now
frichards Nov 18, 2025
f9e64d5
fix: wallet icon
frichards Nov 18, 2025
95abfba
fix: create useNetworksWithBalance hook
frichards Nov 19, 2025
ae81139
fix: make the logic more efficient
frichards Nov 19, 2025
885539c
fix: handing error for wallet total
frichards Nov 19, 2025
ab55c3c
fix: header styling update
frichards Nov 19, 2025
82b51e8
fix: header account clean up and add comments
frichards Nov 19, 2025
400f993
fix(header): bring back the addressList for convenience
frichards Nov 20, 2025
3a847be
fix: add and fix tests and gix bugs
frichards Nov 20, 2025
82f5e4e
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 20, 2025
f39132f
fix: cleaning up
frichards Nov 21, 2025
06dc26d
fix: refactor
frichards Nov 21, 2025
a5d3bce
fix: add imported account details
frichards Nov 21, 2025
f2d36d4
fix: fix a bug on networks with balance
frichards Nov 21, 2025
acaab92
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 21, 2025
7a2459c
fix: clean up
frichards Nov 21, 2025
5320fdc
fix: add missing tests
frichards Nov 21, 2025
d4e08dc
fix: add missing translations
frichards Nov 21, 2025
0136596
fix: addressList position
frichards Nov 21, 2025
28a6c6c
Merge branch 'main' into CP-12484-wallet-level
frichards Nov 21, 2025
11acf13
fix: post code review
frichards Nov 24, 2025
6d480f4
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 24, 2025
5e59524
fix: post merge conflict fix
frichards Nov 24, 2025
f91c51c
fix: styling update
frichards Nov 24, 2025
19e9939
fix: clean up
frichards Nov 24, 2025
d599bf3
Merge branch 'main' into CP-12484-wallet-level
frichards Nov 24, 2025
2ebd51f
Merge remote-tracking branch 'origin/main' into CP-12484-wallet-level
frichards Nov 25, 2025
f286c4e
fix: post code review round 2
frichards Nov 25, 2025
0e4fe6b
fix: tests
frichards Nov 25, 2025
a704260
fix: styling update for the existing components
frichards Nov 24, 2025
98c9ed1
feat: token detail page top parts
frichards Nov 24, 2025
ced19f2
fix: adding filter /sort buttons
frichards Nov 24, 2025
55824b3
fix: token detail page routes update
frichards Nov 24, 2025
9f66c56
fix: adding transaction history in token details
frichards Nov 25, 2025
77fbda9
fix: header to handle tokens
frichards Nov 25, 2025
6ba90d6
fix: route and header fix plus some pchain details
frichards Dec 1, 2025
e11266e
fix: pchain details
frichards Dec 1, 2025
cdf9fdd
fix: intro to xchain details and refactoring
frichards Dec 1, 2025
6c4c6c5
fix: enable x chains
frichards Dec 1, 2025
f6f1d16
fix: styling
frichards Dec 2, 2025
ad099ba
fix: styling refactor
frichards Dec 2, 2025
70b9158
fix: false error state flashing while loading
frichards Dec 2, 2025
79eb2e8
fix: styling update to match the design update
frichards Dec 2, 2025
75d5e0d
Merge remote-tracking branch 'origin/main' into CP-12485-account-view
frichards Dec 2, 2025
023081b
fix: state handling bug fixed for navigating back to token details
frichards Dec 2, 2025
de7d49d
fix: post code review
frichards Dec 3, 2025
647ccbe
fix: fix bugs
frichards Dec 3, 2025
286fd38
fix: refactor
frichards Dec 3, 2025
789a0c8
Merge remote-tracking branch 'origin/main' into CP-12485-account-view
frichards Dec 3, 2025
dfc2bd2
fix: no token acticity component
frichards Dec 3, 2025
385fa1d
Merge remote-tracking branch 'origin/main' into CP-12485-account-view
frichards Dec 3, 2025
dd593e6
fix: add explorer button to all token activities
frichards Dec 3, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ const HeaderAccountContent: FC<Props> = ({ wallet, isTrueWallet, account }) => {
isContainerHovered={isContainerHovered}
/>

{/* Navigation Arrow */}
<IconWrapper shouldShift={false}>
<MdNavigateNext />
</IconWrapper>
{/* Navigation Arrow: Waiting for account to be visible */}
{account && (
<IconWrapper shouldShift={false}>
<MdNavigateNext />
</IconWrapper>
)}

{/* Account Name */}
<AccountSection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FC } from 'react';
import { TruncatedText } from '../../styledComponents';
import { AccountSectionContainer, Label } from '../styled';
import { useTranslation } from 'react-i18next';

type Props = {
tokenTextRef: React.RefObject<HTMLSpanElement | null>;
isTokenTruncated: boolean;
tokenName: string;
isContainerHovered: boolean;
};

export const TokenSection: FC<Props> = ({
tokenTextRef,
isTokenTruncated,
tokenName,
isContainerHovered,
}) => {
const { t } = useTranslation();

return (
<AccountSectionContainer shouldShift={false}>
<TruncatedText
ref={tokenTextRef}
variant="subtitle3"
showFade={isTokenTruncated}
>
{tokenName}
</TruncatedText>
{isContainerHovered && <Label variant="caption">{t('Token')}</Label>}
</AccountSectionContainer>
);
};
14 changes: 14 additions & 0 deletions apps/next/src/localization/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
"Ask Core Concierge to swap tokens": "Ask Core Concierge to swap tokens",
"Ask Core Concierge to transfer for you": "Ask Core Concierge to transfer for you",
"Assets": "Assets",
"Atomic Memory Locked": "Atomic Memory Locked",
"Atomic Memory Unlocked": "Atomic Memory Unlocked",
"Attempted to use an unknown derivation path": "Attempted to use an unknown derivation path",
"Authenticator": "Authenticator",
"Authenticator added!": "Authenticator added!",
Expand Down Expand Up @@ -140,6 +142,7 @@
"Chain ID": "Chain ID",
"Change Authenticator App": "Change Authenticator App",
"Change password": "Change password",
"Check full transaction history on the explorer": "Check full transaction history on the explorer",
"Chinese - Simplified": "Chinese - Simplified",
"Chinese - Traditional": "Chinese - Traditional",
"Choose": "Choose",
Expand Down Expand Up @@ -401,6 +404,9 @@
"Locate the connect button on their site": "Locate the connect button on their site",
"Lock Core": "Lock Core",
"Locked": "Locked",
"Locked Platform": "Locked Platform",
"Locked Stakeable": "Locked Stakeable",
"Locked Staked": "Locked Staked",
"Login": "Login",
"Logo URL": "Logo URL",
"Losing this phrase will result in lost funds": "Losing this phrase will result in lost funds",
Expand Down Expand Up @@ -463,6 +469,7 @@
"No matching results": "No matching results",
"No matching sites found": "No matching sites found",
"No recent transactions": "No recent transactions",
"No recent transctions": "No recent transctions",
"No recovery methods set up": "No recovery methods set up",
"No results found": "No results found",
"No routes found with enough liquidity.": "No routes found with enough liquidity.",
Expand Down Expand Up @@ -757,6 +764,7 @@
"Type": "Type",
"Type in or paste address": "Type in or paste address",
"Type in or paste token contract address": "Type in or paste token contract address",
"UTXOs across multiple addresses": "UTXOs across multiple addresses",
"Unable to cancel the export request. Please contact support.": "Unable to cancel the export request. Please contact support.",
"Unable to connect": "Unable to connect",
"Unable to connect.": "Unable to connect.",
Expand All @@ -782,6 +790,9 @@
"Unlimited": "Unlimited",
"Unlimited {{currency}}": "Unlimited {{currency}}",
"Unlock airdrops": "Unlock airdrops",
"Unlocked": "Unlocked",
"Unlocked Staked": "Unlocked Staked",
"Unlocked Unstaked": "Unlocked Unstaked",
"Unnamed FIDO Device": "Unnamed FIDO Device",
"Unsupporetd secret type": "Unsupporetd secret type",
"Unsupported Version": "Unsupported Version",
Expand Down Expand Up @@ -815,7 +826,10 @@
"Vesting": "Vesting",
"Videos": "Videos",
"View All Connected Sites": "View All Connected Sites",
"View all of your balances and UTXOs": "View all of your balances and UTXOs",
"View full history": "View full history",
"View in Explorer": "View in Explorer",
"View on explorer": "View on explorer",
"View preference": "View preference",
"View the troubleshooting guide <troubleshootButton>here</troubleshootButton>": "View the troubleshooting guide <troubleshootButton>here</troubleshootButton>",
"Waiting for <bold>{{provider}}</bold> authentication to complete": "Waiting for <bold>{{provider}}</bold> authentication to complete",
Expand Down
2 changes: 2 additions & 0 deletions apps/next/src/pages/Portfolio/Portfolio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { AddCustomToken } from './components/AddCustomToken/AddCustomToken';
import { ManageTokens } from './components/ManageTokens';
import { PortfolioHome } from './components/PortfolioHome';
import { WalletView } from './components/WalletView/WalletView';
import { TokenDetails } from './components/PortfolioHome/components/PortolioDetails/components/TokenDetails';

export const Portfolio: FC = () => (
<Switch>
<Route path="/manage-tokens/add-custom" component={AddCustomToken} />
<Route path="/manage-tokens" component={ManageTokens} />
<Route path="/wallet/:walletId" component={WalletView} />
<Route path="/asset/:networkId/:tokenAddress" component={TokenDetails} />
<Route path="/" component={PortfolioHome} />
</Switch>
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
alpha,
CircularProgress,
Stack,
styled,
Expand All @@ -22,6 +21,7 @@ import { useTranslation } from 'react-i18next';
import { TESTNET_MODE_BACKGROUND_COLOR } from '@/config/constants';
import { TestnetModeOverlay } from '@/components/TestnetModeOverlay';
import { useHistory, useLocation } from 'react-router-dom';
import { TabsContainer } from './styled';

export type TabName = 'assets' | 'collectibles' | 'defi' | 'activity';

Expand Down Expand Up @@ -124,18 +124,6 @@ export const PortfolioHome: FC = () => {
);
};

const TabsContainer = styled(Stack)(({ theme }) => ({
position: 'sticky',
bottom: 0,
paddingTop: theme.spacing(1),
zIndex: theme.zIndex.appBar,
background: `linear-gradient(180deg, ${alpha(theme.palette.background.default, 0)} 0%, ${theme.palette.background.default} 16px)`,

'> div': {
background: 'unset',
},
}));

const CenteredSpinner = styled(CircularProgress)({
margin: 'auto',
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { DropdownMenu } from '@/components/DropdownMenu';
import { Box, PopoverItem } from '@avalabs/k2-alpine';
import { FC } from 'react';
import { FC, RefObject, useMemo } from 'react';
import { ActivityFilter } from '../types';
import { useTranslation } from 'react-i18next';

type Props = {
selected: ActivityFilter;
onChange(filter: ActivityFilter): void;
ref?: RefObject<HTMLElement>;
exclude?: ActivityFilter[];
};

const ACTIVITY_FILTERS: ActivityFilter[] = [
Expand All @@ -19,12 +21,21 @@ const ACTIVITY_FILTERS: ActivityFilter[] = [
'NFTs',
];

export const ActivityFilterSelector: FC<Props> = ({ selected, onChange }) => {
export const ActivityFilterSelector: FC<Props> = ({
selected,
onChange,
ref,
exclude,
}) => {
const { t } = useTranslation();
const filteredActivityFilters = useMemo(() => {
return ACTIVITY_FILTERS.filter((filter) => !exclude?.includes(filter));
}, [exclude]);

return (
<Box>
<Box ref={ref}>
<DropdownMenu label={t('Filter')}>
{ACTIVITY_FILTERS.map((filterName) => (
{filteredActivityFilters.map((filterName) => (
<PopoverItem
key={filterName}
onClick={() => onChange(filterName)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { List, ListItem, Typography } from '@avalabs/k2-alpine';
import { NetworkWithCaipId } from '@core/types';
import { FC, Fragment, memo } from 'react';
import { useAccountHistory, useGroupedHistory } from '../../hooks';
import { FC, memo } from 'react';
import { useAccountHistory } from '../../hooks';
import { ActivityFilter } from '../../types';
import { EmptyState } from '../EmptyState';
import * as Styled from './components/Styled';
import { TransactionItem } from './components/TransactionItem';

import { HistoryList } from './components/HistoryList';

type Props = {
filter: ActivityFilter;
Expand All @@ -15,43 +13,8 @@ type Props = {
const TransactionList: FC<Props> = ({ filter, network }) => {
const transactionHistory = useAccountHistory(network);

const groupedTransactionHistory = useGroupedHistory(
transactionHistory,
filter,
);

if (transactionHistory.length === 0) {
return <EmptyState />;
}

return (
<List disablePadding>
{Object.entries(groupedTransactionHistory).map(
([groupName, transactions]) => (
<ListItem key={groupName} disableGutters disablePadding>
<Styled.List
disablePadding
subheader={
<Styled.ListSubheader disableGutters>
<Typography variant="h6" color="text.primary">
{groupName}
</Typography>
</Styled.ListSubheader>
}
>
{transactions.map((tx, index, self) => (
<Fragment key={tx.hash}>
<TransactionItem transaction={tx} />
{index < self.length - 1 && (
<Styled.Divider variant="inset" />
)}
</Fragment>
))}
</Styled.List>
</ListItem>
),
)}
</List>
<HistoryList filter={filter} transactionHistory={transactionHistory} />
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ActivityFilter } from '../../../types';
import { TxHistoryItem } from '@core/types';
import { NetworkVMType } from '@avalabs/vm-module-types';
import { FC, Fragment } from 'react';
import { useGroupedHistory } from '../../../hooks';
import { List, ListItem, Typography } from '@avalabs/k2-alpine';
import { EmptyState } from '@/pages/Portfolio/components/PortfolioHome/components/EmptyState';
import * as Styled from './Styled';
import { TransactionItem } from './TransactionItem';

type Props = {
filter: ActivityFilter;
transactionHistory: TxHistoryItem<NetworkVMType>[];
};

export const HistoryList: FC<Props> = ({ filter, transactionHistory }) => {
const groupedTransactionHistory = useGroupedHistory(
transactionHistory,
filter,
);

if (transactionHistory.length === 0) {
return <EmptyState />;
}

return (
<List disablePadding>
{Object.entries(groupedTransactionHistory).map(
([groupName, transactions]) => (
<ListItem key={groupName} disableGutters disablePadding>
<Styled.List
disablePadding
subheader={
<Styled.ListSubheader disableGutters>
<Typography variant="h6" color="text.primary">
{groupName}
</Typography>
</Styled.ListSubheader>
}
>
{transactions.map((tx, index, self) => (
<Fragment key={tx.hash}>
<TransactionItem transaction={tx} />
{index < self.length - 1 && (
<Styled.Divider variant="inset" />
)}
</Fragment>
))}
</Styled.List>
</ListItem>
),
)}
</List>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import { ProfitAndLoss } from './ProfitAndLoss';
import { FungibleTokenBalance } from '@core/types';
import { TokenAvatar } from '@/components/TokenAvatar';
import { Card } from '@/components/Card';
import { useHistory } from 'react-router-dom';
import { TokenType } from '@avalabs/vm-module-types';

interface AssetCardProps {
asset: FungibleTokenBalance;
onClick?: () => void;
}

const AVATAR_SIZE = 40;
const BADGE_SIZE = 18;
const AVATAR_SIZE = 32;
const BADGE_SIZE = 16;
const CHEVRON_SIZE = 20;
const CARD_BORDER_RADIUS = 2;
const CARD_GAP = 1.5;
Expand All @@ -34,14 +35,14 @@ const formatTokenBalance = (balance: string, symbol: string): string => {
return `${balance} ${symbol}`;
};

export const AssetCard = ({ asset, onClick }: AssetCardProps) => {
export const AssetCard = ({ asset }: AssetCardProps) => {
const theme = useTheme();
const history = useHistory();

const handleClick = () => {
onClick?.();
// TODO: Navigate to asset details page when route is available
// const history = useHistory();
// history.push(`/asset/${asset.symbol}`);
const tokenAddress =
asset.type === TokenType.NATIVE ? asset.symbol : asset.address;
history.push(`/asset/${asset.coreChainId}/${tokenAddress}`);
};

const badgeBorderColor = getBadgeBorderColor(theme);
Expand All @@ -51,15 +52,21 @@ export const AssetCard = ({ asset, onClick }: AssetCardProps) => {
);

return (
<Card sx={{ width: '100%', borderRadius: CARD_BORDER_RADIUS }}>
<Card
sx={{
width: '100%',
borderRadius: CARD_BORDER_RADIUS,
backgroundColor: 'background.paper',
}}
>
<Stack
role="button"
onClick={handleClick}
direction="row"
alignItems="center"
gap={CARD_GAP}
sx={{
cursor: onClick ? 'pointer' : 'default',
cursor: 'pointer',
px: theme.spacing(CARD_PADDING_X),
py: theme.spacing(CARD_PADDING_Y),
}}
Expand All @@ -75,7 +82,7 @@ export const AssetCard = ({ asset, onClick }: AssetCardProps) => {
/>
</Box>

<Stack flexGrow={1} minWidth={0}>
<Stack flexGrow={1} minWidth={0} gap={0}>
<Typography
variant="subtitle3"
noWrap
Expand Down
Loading
Loading