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

refactor(portfolio): simplify getTopTokens and improve naming consistency #6167

Merged
merged 12 commits into from
Jan 16, 2025
21 changes: 13 additions & 8 deletions frontend/src/lib/components/portfolio/TokensCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import { formatNumber } from "$lib/utils/format.utils";
yhabib marked this conversation as resolved.
Show resolved Hide resolved
import { IconAccountsPage, IconRight } from "@dfinity/gix-components";

export let topTokens: UserTokenData[];
export let topHeldTokens: UserTokenData[];
export let usdAmount: number;

const href = AppPath.Tokens;
Expand All @@ -22,7 +22,7 @@

// TODO: This will also depend on the number of projects
let showInfoRow: boolean;
$: showInfoRow = topTokens.length > 0 && topTokens.length < 3;
$: showInfoRow = topHeldTokens.length > 0 && topHeldTokens.length < 3;
</script>

<Card testId="tokens-card">
Expand Down Expand Up @@ -78,29 +78,34 @@
</div>

<div class="tokens-list" role="rowgroup">
{#each topTokens as token (token.domKey)}
{#each topHeldTokens as topHeldToken (topHeldToken.domKey)}
<div class="token-row" data-tid="token-card-row" role="row">
<div class="token-info" role="cell">
<div>
<Logo src={token.logo} alt={token.title} size="medium" framed />
<Logo
src={topHeldToken.logo}
alt={topHeldToken.title}
size="medium"
framed
/>
</div>
<span data-tid="token-title">{token.title}</span>
<span data-tid="token-title">{topHeldToken.title}</span>
</div>

<div
class="token-native-balance"
data-tid="token-native-balance"
role="cell"
>
<AmountDisplay singleLine amount={token.balance} />
<AmountDisplay singleLine amount={topHeldToken.balance} />
</div>
<div
class="token-usd-balance"
data-tid="token-usd-balance"
role="cell"
aria-label={`${token.title} USD: ${token?.balanceInUsd ?? 0}`}
aria-label={`${topHeldToken.title} USD: ${topHeldToken?.balanceInUsd ?? 0}`}
>
${formatNumber(token?.balanceInUsd ?? 0)}
${formatNumber(topHeldToken?.balanceInUsd ?? 0)}
</div>
</div>
{/each}
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/lib/pages/Portfolio.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
import { getTotalBalanceInUsd } from "$lib/utils/token.utils";
import { TokenAmountV2, isNullish } from "@dfinity/utils";

export let userTokensData: UserToken[];
export let userTokens: UserToken[];
export let tableProjects: TableProject[];

let totalTokensBalanceInUsd: number;
$: totalTokensBalanceInUsd = getTotalBalanceInUsd(userTokensData);
$: totalTokensBalanceInUsd = getTotalBalanceInUsd(userTokens);

let hasUnpricedTokens: boolean;
$: hasUnpricedTokens = userTokensData.some(
$: hasUnpricedTokens = userTokens.some(
(token) =>
token.balance instanceof TokenAmountV2 &&
token.balance.toUlps() > 0n &&
Expand Down Expand Up @@ -55,9 +55,9 @@
let hasNoProjectsCardAPrimaryAction: boolean;
$: hasNoProjectsCardAPrimaryAction = !showNoTokensCard;

let topTokens: UserTokenData[];
$: topTokens = getTopTokens({
userTokens: userTokensData,
let topHeldTokens: UserTokenData[];
$: topHeldTokens = getTopTokens({
userTokens: userTokens,
isSignedIn: $authSignedInStore,
});
</script>
Expand All @@ -76,7 +76,7 @@
{#if showNoTokensCard}
<NoTokensCard />
{:else}
<TokensCard {topTokens} usdAmount={totalTokensBalanceInUsd} />
<TokensCard {topHeldTokens} usdAmount={totalTokensBalanceInUsd} />
{/if}
{#if showNoProjectsCard}
<NoProjectsCard primaryCard={hasNoProjectsCardAPrimaryAction} />
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/lib/utils/portfolio.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,20 @@ const compareTokens = mergeComparators([
* - Always prioritizes ICP token first
* - Sorts remaining tokens by USD balance
* - Sorts remaining tokens by importance
* - Limits the number of returned tokens to maxTokensToShow
* - Limits the number of returned tokens to MAX_NUMBER_OF_ITEMS
* - When isSigned true, filters out tokens with zero balance as we show only tokens with guaranteed balance
*/
export const getTopTokens = ({
userTokens,
maxResults = MAX_NUMBER_OF_ITEMS,
isSignedIn = false,
}: {
userTokens: UserToken[];
maxResults?: number;
isSignedIn?: boolean;
}): UserTokenData[] => {
const topTokens = userTokens
.filter(isUserTokenData)
.sort(compareTokens)
.slice(0, maxResults);
.slice(0, MAX_NUMBER_OF_ITEMS);

if (!isSignedIn) return topTokens;

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/(app)/(nns)/portfolio/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

<TestIdWrapper testId="portfolio-route-component"
><Portfolio
userTokensData={userTokens}
{userTokens}
tableProjects={getTableProjects({
universes: $selectableUniversesStore,
isSignedIn: $authSignedInStore,
Expand Down
16 changes: 8 additions & 8 deletions frontend/src/tests/lib/components/portfolio/TokensCard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { render } from "@testing-library/svelte";

describe("TokensCard", () => {
const renderComponent = (props: {
topTokens: UserTokenData[];
topHeldTokens: UserTokenData[];
usdAmount: number;
}) => {
const { container } = render(TokensCard, {
Expand All @@ -43,7 +43,7 @@ describe("TokensCard", () => {

it("should show placeholder balance", async () => {
const po = renderComponent({
topTokens: mockTokens,
topHeldTokens: mockTokens,
usdAmount: 0,
});

Expand All @@ -52,7 +52,7 @@ describe("TokensCard", () => {

it("should show list of tokens with name and balance", async () => {
const po = renderComponent({
topTokens: mockTokens,
topHeldTokens: mockTokens,
usdAmount: 0,
});
const titles = await po.getTokensTitles();
Expand Down Expand Up @@ -100,7 +100,7 @@ describe("TokensCard", () => {

it("should show the usd amount", async () => {
const po = renderComponent({
topTokens: mockTokens,
topHeldTokens: mockTokens,
usdAmount: 600,
});

Expand All @@ -109,7 +109,7 @@ describe("TokensCard", () => {

it("should show all the tokens with their balance", async () => {
const po = renderComponent({
topTokens: mockTokens,
topHeldTokens: mockTokens,
usdAmount: 600,
});
const titles = await po.getTokensTitles();
Expand All @@ -132,7 +132,7 @@ describe("TokensCard", () => {

it("should not show info row when tokens length is 3 or more", async () => {
const po = renderComponent({
topTokens: mockTokens.slice(0, 3),
topHeldTokens: mockTokens.slice(0, 3),
usdAmount: 600,
});
const titles = await po.getTokensTitles();
Expand All @@ -157,7 +157,7 @@ describe("TokensCard", () => {

it("should show info row when tokens length is 1", async () => {
const po = renderComponent({
topTokens: mockTokens.slice(0, 1),
topHeldTokens: mockTokens.slice(0, 1),
usdAmount: 100,
});

Expand All @@ -179,7 +179,7 @@ describe("TokensCard", () => {

it("should show info row when tokens length is 2", async () => {
const po = renderComponent({
topTokens: mockTokens.slice(0, 2),
topHeldTokens: mockTokens.slice(0, 2),
usdAmount: 300,
});

Expand Down
18 changes: 9 additions & 9 deletions frontend/src/tests/lib/pages/Portfolio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import { render } from "@testing-library/svelte";

describe("Portfolio page", () => {
const renderPage = ({
userTokensData = [],
userTokens = [],
tableProjects = [],
}: { userTokensData?: UserToken[]; tableProjects?: TableProject[] } = {}) => {
}: { userTokens?: UserToken[]; tableProjects?: TableProject[] } = {}) => {
const { container } = render(Portfolio, {
props: {
userTokensData,
userTokens,
tableProjects,
},
});
Expand Down Expand Up @@ -91,7 +91,7 @@ describe("Portfolio page", () => {
universeId: principal(1),
balanceInUsd: 2,
});
const po = renderPage({ userTokensData: [token] });
const po = renderPage({ userTokens: [token] });

expect(await po.getNoTokensCard().isPresent()).toBe(false);
expect(await po.getTokensCardPo().isPresent()).toBe(true);
Expand Down Expand Up @@ -148,7 +148,7 @@ describe("Portfolio page", () => {

it("should display the top four tokens by balanceInUsd", async () => {
const po = renderPage({
userTokensData: [token1, token2, token3, token4, token5],
userTokens: [token1, token2, token3, token4, token5],
});
const tokensCardPo = po.getTokensCardPo();

Expand Down Expand Up @@ -182,7 +182,7 @@ describe("Portfolio page", () => {

it("should display the information row when less then three tokens", async () => {
const po = renderPage({
userTokensData: [token1, token2],
userTokens: [token1, token2],
});
const tokensCardPo = po.getTokensCardPo();

Expand Down Expand Up @@ -229,7 +229,7 @@ describe("Portfolio page", () => {
universeId: principal(1),
balanceInUsd: 2,
});
const po = renderPage({ userTokensData: [token] });
const po = renderPage({ userTokens: [token] });

expect(await po.getNoNeuronsCarPo().isPresent()).toBe(true);
expect(await po.getNoNeuronsCarPo().hasPrimaryAction()).toBe(true);
Expand Down Expand Up @@ -277,7 +277,7 @@ describe("Portfolio page", () => {

it("should display total assets", async () => {
const po = renderPage({
userTokensData: [token1, token2],
userTokens: [token1, token2],
tableProjects: [tableProject1, tableProject2],
});

Expand All @@ -295,7 +295,7 @@ describe("Portfolio page", () => {
});

it("should ignore tokens with unknown balance in USD and display tooltip", async () => {
const po = renderPage({ userTokensData: [token1, token2, token3] });
const po = renderPage({ userTokens: [token1, token2, token3] });

expect(await po.getUsdValueBannerPo().getPrimaryAmount()).toBe(
"$12.00"
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/tests/lib/utils/portfolio.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ describe("Portfolio utils", () => {
];
const result = getTopTokens({
userTokens: tokens,
maxResults: 3,
});

expect(result).toHaveLength(3);
expect(result).toHaveLength(4);
});

it("should order tokens: ICP first, then ckBTC/ckUSDC, then others", () => {
Expand Down
Loading