From 8edb97d9c3febd61aec80422eafeafe9b08397df Mon Sep 17 00:00:00 2001 From: Max Strasinsky <98811342+mstrasinskis@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:15:58 +0200 Subject: [PATCH] Redirection on unknown token. (#5528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Motivation When the user is on the imported token wallet page and the sign-out timer expires, the page reloads, leaving the user on an empty page. This happens because imported tokens are available only when the user is signed in. Upon sign-out, we no longer know the type of the token (whether it’s ICRC or not). Rather than making guesses, it’s more reliable to navigate the user to the main tokens page in this case. # Changes - Navigate to the tokens table when it’s not possible to identify the token. Since this logic is not intended to be reused, it is implemented directly in the component rather than in a derived store. # Tests - Added. # Todos - [ ] Add entry to changelog (if necessary). Not necessary. --- frontend/src/lib/routes/Wallet.svelte | 19 +++++++++ frontend/src/tests/lib/routes/Wallet.spec.ts | 41 +++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/frontend/src/lib/routes/Wallet.svelte b/frontend/src/lib/routes/Wallet.svelte index ec41378ebe9..d0864a77f44 100644 --- a/frontend/src/lib/routes/Wallet.svelte +++ b/frontend/src/lib/routes/Wallet.svelte @@ -16,12 +16,31 @@ import { i18n } from "$lib/stores/i18n"; import { layoutTitleStore } from "$lib/stores/layout.store"; import { nonNullish } from "@dfinity/utils"; + import { AppPath } from "$lib/constants/routes.constants"; + import { goto } from "$app/navigation"; + import { snsAggregatorStore } from "$lib/stores/sns-aggregator.store"; export let accountIdentifier: string | undefined | null = undefined; layoutTitleStore.set({ title: $i18n.wallet.title, }); + + let isUnknownToken = false; + $: isUnknownToken = + !$isNnsUniverseStore && + !$isCkBTCUniverseStore && + !$isIcrcTokenUniverseStore && + // We can't be sure that the token is unknown + // before we have the list of Sns projects. + nonNullish($snsAggregatorStore.data) && + !nonNullish($snsProjectSelectedStore); + $: if (isUnknownToken) { + // This will also cover the case when the user was logged out + // being on the wallet page of an imported token + // (imported tokens are not available when signed out). + goto(AppPath.Tokens); + } diff --git a/frontend/src/tests/lib/routes/Wallet.spec.ts b/frontend/src/tests/lib/routes/Wallet.spec.ts index 4f1b117906d..1d19ea7d8bd 100644 --- a/frontend/src/tests/lib/routes/Wallet.spec.ts +++ b/frontend/src/tests/lib/routes/Wallet.spec.ts @@ -1,5 +1,6 @@ import * as ckbtcMinterApi from "$lib/api/ckbtc-minter.api"; import * as governanceApi from "$lib/api/governance.api"; +import * as icpIndexApi from "$lib/api/icp-index.api"; import * as icrcLedgerApi from "$lib/api/icrc-ledger.api"; import { OWN_CANISTER_ID_TEXT } from "$lib/constants/canister-ids.constants"; import { CKBTC_UNIVERSE_CANISTER_ID } from "$lib/constants/ckbtc-canister-ids.constants"; @@ -8,6 +9,7 @@ import { CKETH_UNIVERSE_CANISTER_ID, } from "$lib/constants/cketh-canister-ids.constants"; import { AppPath } from "$lib/constants/routes.constants"; +import { pageStore } from "$lib/derived/page.derived"; import Wallet from "$lib/routes/Wallet.svelte"; import { authStore } from "$lib/stores/auth.store"; import { icrcAccountsStore } from "$lib/stores/icrc-accounts.store"; @@ -30,11 +32,12 @@ import { WalletPo } from "$tests/page-objects/Wallet.page-object"; import { JestPageObjectElement } from "$tests/page-objects/jest.page-object"; import { setAccountsForTesting } from "$tests/utils/accounts.test-utils"; import { setCkETHCanisters } from "$tests/utils/cketh.test-utils"; -import { setSnsProjects } from "$tests/utils/sns.test-utils"; +import { resetSnsProjects, setSnsProjects } from "$tests/utils/sns.test-utils"; import { runResolvedPromises } from "$tests/utils/timers.test-utils"; import { encodeIcrcAccount } from "@dfinity/ledger-icrc"; import { SnsSwapLifecycle } from "@dfinity/sns"; import { render } from "@testing-library/svelte"; +import { get } from "svelte/store"; vi.mock("$lib/api/icrc-ledger.api"); vi.mock("$lib/api/ckbtc-minter.api"); @@ -270,4 +273,40 @@ describe("Wallet", () => { expect(await pagePo.getWalletPageHeadingPo().getTitle()).toBe("1.11 ckETH"); }); + + describe("unknown token", () => { + const unknownUniverseId = "aaaaa-aa"; + + beforeEach(() => { + // Mock the getTransactions call from the Tokens page. + vi.spyOn(icpIndexApi, "getTransactions").mockResolvedValue({ + transactions: [], + oldestTxId: undefined, + } as icpIndexApi.GetTransactionsResponse); + }); + + it("redirect to tokens when unknown universe", async () => { + page.mock({ + data: { universe: unknownUniverseId }, + routeId: AppPath.Wallet, + }); + resetSnsProjects(); + + expect(get(pageStore).path).toEqual(AppPath.Wallet); + + render(Wallet, { + props: { + accountIdentifier: undefined, + }, + }); + await runResolvedPromises(); + + // Waits for the sns projects to be available + expect(get(pageStore).path).toEqual(AppPath.Wallet); + setSnsProjects([{}]); + await runResolvedPromises(); + + expect(get(pageStore).path).toEqual(AppPath.Tokens); + }); + }); });