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

Ledger neuron hotkey warning #6061

Merged
merged 8 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
import { browser } from "$app/environment";
import { i18n } from "$lib/stores/i18n";
import { IconInfo } from "@dfinity/gix-components";
import Banner from "../ui/Banner.svelte";
import BannerIcon from "../ui/BannerIcon.svelte";
import TestIdWrapper from "../common/TestIdWrapper.svelte";

const LOCAL_STORAGE_KEY = "isLedgerNeuronHotkeyWarningDisabled";

let isDismissed = browser
? Boolean(JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY) ?? "false"))
: false;
let isVisible = false;
$: isVisible = !isDismissed;

function dismissBanner() {
isDismissed = true;
localStorage.setItem(LOCAL_STORAGE_KEY, "true");
}
</script>

<TestIdWrapper testId="ledger-neuron-hotkey-warning-component">
{#if isVisible}
<Banner
isClosable
on:nnsClose={dismissBanner}
htmlText={$i18n.losing_rewards.hw_hotkey_warning}
>
<BannerIcon slot="icon">
<IconInfo />
</BannerIcon>
</Banner>
{/if}
</TestIdWrapper>
3 changes: 2 additions & 1 deletion frontend/src/lib/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@
"losing_rewards": {
"description": "ICP neurons that are inactive for $period start missing voting rewards. To avoid missing rewards, vote manually, edit, or confirm your following.",
"confirming": "Confirming following. This may take a moment.",
"confirm": "Confirm Following"
"confirm": "Confirm Following",
"hw_hotkey_warning": "You may have neurons that are not added to the NNS dapp. If you want to view your neurons and get alerts in case they start missing voting rewards, you can add them by clicking <strong>Show Neurons > Add to NNS Dapp</strong>."
},
"losing_rewards_banner": {
"confirm_title": "Confirm following or vote manually to avoid missing rewards",
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/lib/pages/NnsWallet.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
} from "@dfinity/utils";
import { onDestroy, onMount, setContext } from "svelte";
import { writable, type Readable } from "svelte/store";
import { ENABLE_PERIODIC_FOLLOWING_CONFIRMATION } from "$lib/stores/feature-flags.store";
import LedgerNeuronHotkeyWarning from "$lib/components/accounts/LedgerNeuronHotkeyWarning.svelte";

$: if ($authSignedInStore) {
pollAccounts();
Expand Down Expand Up @@ -381,6 +383,10 @@
<SignInGuard />
</WalletPageHeading>

{#if $ENABLE_PERIODIC_FOLLOWING_CONFIRMATION && isHardwareWallet}
<LedgerNeuronHotkeyWarning />
{/if}

<Separator spacing="none" />

{#if $selectedAccountStore.account !== undefined}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/types/i18n.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ interface I18nLosing_rewards {
description: string;
confirming: string;
confirm: string;
hw_hotkey_warning: string;
}

interface I18nLosing_rewards_banner {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import LedgerNeuronHotkeyWarning from "$lib/components/accounts/LedgerNeuronHotkeyWarning.svelte";
import { LedgerNeuronHotkeyWarningPo } from "$tests/page-objects/LedgerNeuronHotkeyWarning.page-object";
import { JestPageObjectElement } from "$tests/page-objects/jest.page-object";
import { render } from "@testing-library/svelte";

describe("LedgerNeuronHotkeyWarning", () => {
const localStorageKey = "isLedgerNeuronHotkeyWarningDisabled";
const renderComponent = () => {
const { container } = render(LedgerNeuronHotkeyWarning);
return LedgerNeuronHotkeyWarningPo.under(
new JestPageObjectElement(container)
);
};

beforeEach(() => {
localStorage.clear();
});

it("should be shown when localStorageKey not set", async () => {
const po = await renderComponent();
expect(localStorage.getItem(localStorageKey)).toBeNull();

expect(await po.isBannerVisible()).toBe(true);
});

it("should not render when localStorageKey is set to true", async () => {
localStorage.setItem(localStorageKey, "true");
const po = await renderComponent();

expect(await po.isBannerVisible()).toBe(false);
});

it("should be closable", async () => {
const po = await renderComponent();

expect(await po.isBannerVisible()).toBe(true);
expect(localStorage.getItem(localStorageKey)).toBeNull();

await po.getBannerPo().clickClose();

expect(await po.isBannerVisible()).toBe(false);
expect(localStorage.getItem(localStorageKey)).toEqual("true");
});
});
36 changes: 36 additions & 0 deletions frontend/src/tests/lib/pages/NnsWallet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { AppPath } from "$lib/constants/routes.constants";
import { pageStore } from "$lib/derived/page.derived";
import NnsWallet from "$lib/pages/NnsWallet.svelte";
import { cancelPollAccounts } from "$lib/services/icp-accounts.services";
import { overrideFeatureFlagsStore } from "$lib/stores/feature-flags.store";
import { icpTransactionsStore } from "$lib/stores/icp-transactions.store";
import { neuronsStore } from "$lib/stores/neurons.store";
import { getSwapCanisterAccount } from "$lib/utils/sns.utils";
Expand Down Expand Up @@ -408,6 +409,17 @@ describe("NnsWallet", () => {
expect(await po.getWalletPageHeadingPo().getTitle()).toBe("4.32 ICP");
});

it("should not render Ledger neuron hotkey warning for not HW wallet", async () => {
overrideFeatureFlagsStore.setFlag(
"ENABLE_PERIODIC_FOLLOWING_CONFIRMATION",
true
);
const po = await renderWallet(props);
expect(await po.getLedgerNeuronHotkeyWarningPo().isBannerVisible()).toBe(
false
);
});

it("should reload balance on open", async () => {
const oldBalance = 135_000_000n;
const oldBalanceFormatted = "1.35 ICP";
Expand Down Expand Up @@ -1008,6 +1020,30 @@ describe("NnsWallet", () => {
expect(await po.getShowHardwareWalletButtonPo().isPresent()).toBe(true);
});

it("should display Ledger neuron hotkey warning", async () => {
overrideFeatureFlagsStore.setFlag(
"ENABLE_PERIODIC_FOLLOWING_CONFIRMATION",
true
);
const po = await renderWallet(props);

expect(await po.getLedgerNeuronHotkeyWarningPo().isBannerVisible()).toBe(
true
);
});

it("should not display Ledger neuron hotkey warning when feature flag off", async () => {
overrideFeatureFlagsStore.setFlag(
"ENABLE_PERIODIC_FOLLOWING_CONFIRMATION",
false
);
const po = await renderWallet(props);

expect(await po.getLedgerNeuronHotkeyWarningPo().isBannerVisible()).toBe(
false
);
});

describe("when there are staking transactions", () => {
const neuronController = testHwPrincipal;
const memo = 54321n;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { BasePageObject } from "$tests/page-objects/base.page-object";
import type { PageObjectElement } from "$tests/types/page-object.types";
import { BannerPo } from "./Banner.page-object";

export class LedgerNeuronHotkeyWarningPo extends BasePageObject {
private static readonly TID = "ledger-neuron-hotkey-warning-component";

static under(element: PageObjectElement): LedgerNeuronHotkeyWarningPo {
return new LedgerNeuronHotkeyWarningPo(
element.byTestId(LedgerNeuronHotkeyWarningPo.TID)
);
}

getBannerPo(): BannerPo {
return BannerPo.under(this.root);
}

async isBannerVisible(): Promise<boolean> {
return this.getBannerPo().isPresent();
}
}
5 changes: 5 additions & 0 deletions frontend/src/tests/page-objects/NnsWallet.page-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { WalletPageHeaderPo } from "$tests/page-objects/WalletPageHeader.page-ob
import { WalletPageHeadingPo } from "$tests/page-objects/WalletPageHeading.page-object";
import { BasePageObject } from "$tests/page-objects/base.page-object";
import type { PageObjectElement } from "$tests/types/page-object.types";
import { LedgerNeuronHotkeyWarningPo } from "./LedgerNeuronHotkeyWarning.page-object";
import { UiTransactionsListPo } from "./UiTransactionsList.page-object";

export class NnsWalletPo extends BasePageObject {
Expand Down Expand Up @@ -51,6 +52,10 @@ export class NnsWalletPo extends BasePageObject {
return this.getButton("ledger-list-button");
}

getLedgerNeuronHotkeyWarningPo(): LedgerNeuronHotkeyWarningPo {
return LedgerNeuronHotkeyWarningPo.under(this.root);
}

getShowHardwareWalletButtonPo(): ButtonPo {
return this.getButton("ledger-show-button");
}
Expand Down
Loading