From 01e3f7bd073a4933b1a00e1056a476fc2b7184fa Mon Sep 17 00:00:00 2001 From: Andrea Scartabelli Date: Mon, 16 Dec 2024 16:43:24 +0100 Subject: [PATCH] web-wallet: Update default gas settings values - Add button to reset gas settings to their defaults - Fix dark mode button not being in sync with the stored value - Fix `BigIntInput` properties not being reactive Resolves #3178 --- web-wallet/CHANGELOG.md | 6 +++ web-wallet/README.md | 2 +- .../components/BigIntInput/BigIntInput.svelte | 20 +++++---- .../__snapshots__/GasFee.spec.js.snap | 2 +- .../__snapshots__/GasSettings.spec.js.snap | 4 +- .../stores/__tests__/settingsStore.spec.js | 39 ++++++++++++++++ web-wallet/src/lib/stores/gasStore.js | 4 +- web-wallet/src/lib/stores/settingsStore.js | 11 ++++- web-wallet/src/lib/stores/stores.d.ts | 5 ++- .../__tests__/__snapshots__/page.spec.js.snap | 2 +- .../src/routes/(app)/settings/+page.svelte | 44 ++++++++++++------- .../__tests__/__snapshots__/page.spec.js.snap | 33 ++++++++++++++ .../(app)/settings/__tests__/page.spec.js | 33 +++++++++----- web-wallet/vite.config.js | 2 +- 14 files changed, 161 insertions(+), 46 deletions(-) diff --git a/web-wallet/CHANGELOG.md b/web-wallet/CHANGELOG.md index 5a2090add9..09b7fb56b2 100644 --- a/web-wallet/CHANGELOG.md +++ b/web-wallet/CHANGELOG.md @@ -11,12 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add notice for stake maturity [#2981] - Add capability to maintain cache consistency in case of rejected blocks [#3156] +- Add button to reset gas settings to their defaults [#3178] ### Changed - Update Transactions list design [#1922] - Reword "Staking" header to "Stake" [#3113] - Upgrade Migration Feature to Use Reown AppKit [#3129] +- Update default gas settings values [#3178] ### Removed @@ -24,6 +26,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fix dark mode button not being in sync with the stored value [#3178] +- Fix `BigIntInput` properties not being reactive [#3178] + ## [0.9.0] - 2024-12-03 ### Added @@ -434,6 +439,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#3129]: https://github.com/dusk-network/rusk/issues/3129 [#3156]: https://github.com/dusk-network/rusk/issues/3156 [#3160]: https://github.com/dusk-network/rusk/issues/3160 +[#3178]: https://github.com/dusk-network/rusk/issues/3178 diff --git a/web-wallet/README.md b/web-wallet/README.md index 117137c3e9..b7f46bfbbd 100644 --- a/web-wallet/README.md +++ b/web-wallet/README.md @@ -39,7 +39,7 @@ VITE_FEATURE_MOONLIGHT_TRANSACTIONS=true VITE_FEATURE_STAKE=true VITE_FEATURE_TRANSFER=true VITE_FEATURE_TRANSACTION_HISTORY=true -VITE_GAS_LIMIT_DEFAULT=2900000000 +VITE_GAS_LIMIT_DEFAULT=100000000 VITE_GAS_LIMIT_LOWER=10000000 VITE_GAS_LIMIT_UPPER=1000000000 VITE_GAS_PRICE_DEFAULT=1 diff --git a/web-wallet/src/lib/components/BigIntInput/BigIntInput.svelte b/web-wallet/src/lib/components/BigIntInput/BigIntInput.svelte index a5a4ac8a5e..55e5ec05b0 100644 --- a/web-wallet/src/lib/components/BigIntInput/BigIntInput.svelte +++ b/web-wallet/src/lib/components/BigIntInput/BigIntInput.svelte @@ -20,12 +20,13 @@ /** @type {bigint} */ export let value = 0n; - let isInvalidInput = false; let internalValue = value.toString(); + /** @type {(v: bigint, min: bigint, max: bigint) => boolean} */ + const isInvalidInput = (v, min, max) => !!(min > v || v > max); + const checkValidity = () => { - isInvalidInput = !!(minValue > value || value > maxValue); - if (isInvalidInput) { + if (isInvalidInput(value, minValue, maxValue)) { dispatch("error", "Value exceeds limits"); } }; @@ -40,14 +41,17 @@ } } - $: inputClass = makeClassName({ - "invalid-input": isInvalidInput, - [`${className}`]: true, - }); - onMount(() => { checkValidity(); }); + + $: inputClass = makeClassName({ + "invalid-input": isInvalidInput(value, minValue, maxValue), + [`${className}`]: true, + }); + $: { + internalValue = value.toString(); + } renders the GasFee component 1`] = ` - 0.020000000 + 0.100000000 diff --git a/web-wallet/src/lib/components/__tests__/__snapshots__/GasSettings.spec.js.snap b/web-wallet/src/lib/components/__tests__/__snapshots__/GasSettings.spec.js.snap index 13a93aaf29..fad53a6929 100644 --- a/web-wallet/src/lib/components/__tests__/__snapshots__/GasSettings.spec.js.snap +++ b/web-wallet/src/lib/components/__tests__/__snapshots__/GasSettings.spec.js.snap @@ -29,7 +29,7 @@ exports[`GasSettings > renders the GasSettings component closed 1`] = ` - 0.020000000 + 0.100000000 @@ -93,7 +93,7 @@ exports[`GasSettings > renders the GasSettings component opened 1`] = ` - 0.020000000 + 0.100000000 diff --git a/web-wallet/src/lib/stores/__tests__/settingsStore.spec.js b/web-wallet/src/lib/stores/__tests__/settingsStore.spec.js index ce7db5504f..2bce7b43e4 100644 --- a/web-wallet/src/lib/stores/__tests__/settingsStore.spec.js +++ b/web-wallet/src/lib/stores/__tests__/settingsStore.spec.js @@ -126,6 +126,45 @@ describe("Settings store", () => { expect(get(settingsStore)).toBe(settingsStoreContent); }); + + it("should expose a method to reset the gas settings to their defaults", () => { + const newStateWithoutGas = { + currency: "FAKE CURRENCY", + darkMode: !settingsStoreContent.darkMode, + dashboardTransactionLimit: + settingsStoreContent.dashboardTransactionLimit + 1, + hideStakingNotice: !settingsStoreContent.hideStakingNotice, + language: "FAKE LANGUAGE", + userId: "FAKE USER ID", + }; + const newState = { + ...newStateWithoutGas, + gasLimit: settingsStoreContent.gasLimit * 2n, + gasPrice: settingsStoreContent.gasPrice * 15n, + }; + const expectedState = { + ...settingsStoreContent, + ...newStateWithoutGas, + }; + + settingsStore.set(newState); + + expect(get(settingsStore)).toBe(newState); + + settingsStore.resetGasSettings(); + + expect(get(settingsStore)).toStrictEqual(expectedState); + expect( + JSON.parse( + // @ts-ignore + localStorage.getItem(`${CONFIG.LOCAL_STORAGE_APP_KEY}-preferences`) + ) + ).toStrictEqual({ + ...expectedState, + gasLimit: `${expectedState.gasLimit}n`, + gasPrice: `${expectedState.gasPrice}n`, + }); + }); }); describe("In a non browser environment", () => { diff --git a/web-wallet/src/lib/stores/gasStore.js b/web-wallet/src/lib/stores/gasStore.js index 1a3f631372..0a048c683a 100644 --- a/web-wallet/src/lib/stores/gasStore.js +++ b/web-wallet/src/lib/stores/gasStore.js @@ -1,8 +1,8 @@ import { readable } from "svelte/store"; const gasLimits = { - gasLimitLower: BigInt(import.meta.env.VITE_GAS_LIMIT_LOWER ?? 10000000), - gasLimitUpper: BigInt(import.meta.env.VITE_GAS_LIMIT_UPPER ?? 1000000000), + gasLimitLower: BigInt(import.meta.env.VITE_GAS_LIMIT_LOWER ?? 10_000_000), + gasLimitUpper: BigInt(import.meta.env.VITE_GAS_LIMIT_UPPER ?? 1_000_000_000), gasPriceLower: BigInt(import.meta.env.VITE_GAS_PRICE_LOWER ?? 1), }; diff --git a/web-wallet/src/lib/stores/settingsStore.js b/web-wallet/src/lib/stores/settingsStore.js index e2f522e7bb..4e80ff1df0 100644 --- a/web-wallet/src/lib/stores/settingsStore.js +++ b/web-wallet/src/lib/stores/settingsStore.js @@ -32,7 +32,7 @@ const initialState = { ...browserDefaults, currency: "USD", dashboardTransactionLimit: 5, - gasLimit: BigInt(import.meta.env.VITE_GAS_LIMIT_DEFAULT ?? 20000000), + gasLimit: BigInt(import.meta.env.VITE_GAS_LIMIT_DEFAULT ?? 100_000_000), gasPrice: BigInt(import.meta.env.VITE_GAS_PRICE_DEFAULT ?? 1), hideStakingNotice: false, userId: "", @@ -71,9 +71,18 @@ const { set, subscribe, update } = settingsStore; // Reset store to initial state const reset = () => set(initialState); +// Resets only gas settings to their defaults. +const resetGasSettings = () => + update((current) => ({ + ...current, + gasLimit: initialState.gasLimit, + gasPrice: initialState.gasPrice, + })); + /** @type {SettingsStore} */ export default { reset, + resetGasSettings, set, subscribe, update, diff --git a/web-wallet/src/lib/stores/stores.d.ts b/web-wallet/src/lib/stores/stores.d.ts index 6b5bf83c8b..e325990b69 100644 --- a/web-wallet/src/lib/stores/stores.d.ts +++ b/web-wallet/src/lib/stores/stores.d.ts @@ -21,7 +21,10 @@ type SettingsStoreContent = { userId: string; }; -type SettingsStore = Writable & { reset: () => void }; +type SettingsStore = Writable & { + reset: () => void; + resetGasSettings: () => void; +}; type TransactionInfo = | { diff --git a/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap b/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap index dac0135539..7e1b291405 100644 --- a/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap +++ b/web-wallet/src/routes/(app)/dashboard/allocate/__tests__/__snapshots__/page.spec.js.snap @@ -198,7 +198,7 @@ exports[`Allocate > should render the allocation page 1`] = ` - 0.020000000 + 0.100000000 diff --git a/web-wallet/src/routes/(app)/settings/+page.svelte b/web-wallet/src/routes/(app)/settings/+page.svelte index 60315dbe02..c75de6a9a2 100644 --- a/web-wallet/src/routes/(app)/settings/+page.svelte +++ b/web-wallet/src/routes/(app)/settings/+page.svelte @@ -24,7 +24,9 @@ import { logout } from "$lib/navigation"; import loginInfoStorage from "$lib/services/loginInfoStorage"; - const confirmResetMessage = + const confirmResetGasMessage = + "Are you sure you want to reset the gas settings to their defaults?"; + const confirmResetWalletMessage = "Confirm you've saved your recovery phrase before resetting the wallet. Proceed?"; const resetWallet = () => @@ -39,9 +41,16 @@ resetError = err; }); + function handleResetGasSettingsClick() { + // eslint-disable-next-line no-alert + if (confirm(confirmResetGasMessage)) { + settingsStore.resetGasSettings(); + } + } + function handleResetWalletClick() { // eslint-disable-next-line no-alert - if (confirm(confirmResetMessage)) { + if (confirm(confirmResetWalletMessage)) { resetError = null; resetWallet(); } @@ -50,16 +59,15 @@ /** @type {(currency: { code: string, currency: string }) => SelectOption} */ const currencyToOption = rename({ code: "value", currency: "label" }); const currenciesToOptions = mapWith(currencyToOption); - const { currency, darkMode, gasLimit, gasPrice } = $settingsStore; const { gasLimitLower, gasLimitUpper, gasPriceLower } = $gasStore; - let isDarkMode = darkMode; let isGasValid = false; /** @type {Error | null} */ let resetError = null; $: ({ syncStatus } = $walletStore); + $: ({ currency, darkMode, gasLimit, gasPrice } = $settingsStore);
@@ -76,18 +84,16 @@
{ - isGasValid = areValidGasSettings( - event.detail.price, - event.detail.limit - ); + const { limit, price } = event.detail; - if (isGasValid) { - settingsStore.update((store) => { - store.gasLimit = event.detail.limit; - store.gasPrice = event.detail.price; + isGasValid = areValidGasSettings(price, limit); - return store; - }); + if (isGasValid) { + settingsStore.update((store) => ({ + ...store, + gasLimit: limit, + gasPrice: price, + })); } }} limit={gasLimit} @@ -96,6 +102,10 @@ price={gasPrice} priceLower={gasPriceLower} /> +

@@ -132,14 +142,14 @@ > Dark mode { + on:change={(event) => { settingsStore.update((store) => { - store.darkMode = isDarkMode; + store.darkMode = event.detail; return store; }); }} + value={darkMode} /> diff --git a/web-wallet/src/routes/(app)/settings/__tests__/__snapshots__/page.spec.js.snap b/web-wallet/src/routes/(app)/settings/__tests__/__snapshots__/page.spec.js.snap index 003678f335..f15dcd27f7 100644 --- a/web-wallet/src/routes/(app)/settings/__tests__/__snapshots__/page.spec.js.snap +++ b/web-wallet/src/routes/(app)/settings/__tests__/__snapshots__/page.spec.js.snap @@ -79,6 +79,17 @@ exports[`Settings > Resetting the wallet > should show an error if clearing loca /> + + @@ -631,6 +642,17 @@ exports[`Settings > should render the settings page displaying the status of the /> + + @@ -1165,6 +1187,17 @@ exports[`Settings > should render the settings page displaying the status of the /> + + diff --git a/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js b/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js index 6f77c9fc2c..cda6be7324 100644 --- a/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js +++ b/web-wallet/src/routes/(app)/settings/__tests__/page.spec.js @@ -8,10 +8,16 @@ import { vi, } from "vitest"; import { act, cleanup, fireEvent, render } from "@testing-library/svelte"; +import { get } from "svelte/store"; import mockedWalletStore from "../../../../__mocks__/mockedWalletStore"; import * as navigation from "$lib/navigation"; -import { networkStore, settingsStore, walletStore } from "$lib/stores"; +import { + gasStore, + networkStore, + settingsStore, + walletStore, +} from "$lib/stores"; import loginInfoStorage from "$lib/services/loginInfoStorage"; import Settings from "../+page.svelte"; @@ -77,9 +83,9 @@ describe("Settings", () => { expect(container.firstChild).toMatchSnapshot(); }); - it("should disable the reset button while a sync is in progress", async () => { + it("should disable the reset wallet button while a sync is in progress", async () => { const { getByRole } = render(Settings); - const resetButton = getByRole("button", { name: /reset/i }); + const resetButton = getByRole("button", { name: /reset wallet/i }); expect(resetButton).not.toHaveAttribute("disabled"); expect(resetButton).toHaveAttribute("data-tooltip-disabled", "true"); @@ -96,19 +102,24 @@ describe("Settings", () => { }); it('should disable the "Back" button if invalid gas limit or price are introduced', async () => { + const { gasLimitLower, gasLimitUpper, gasPriceLower } = get(gasStore); const { getByLabelText, getByRole } = render(Settings, {}); const priceInput = asInput(getByLabelText(/price/i)); const limitInput = asInput(getByLabelText(/limit/i)); const backButton = getByRole("link", { name: /back/i }); - await fireInput(priceInput, 30000000); + await fireInput(priceInput, String(gasPriceLower - 1n)); expect(backButton).toHaveAttribute("aria-disabled", "true"); - await fireInput(priceInput, 20000000); + await fireInput(priceInput, gasPriceLower.toString()); expect(backButton).toHaveAttribute("aria-disabled", "false"); - await fireInput(limitInput, 3000000000); + await fireInput(limitInput, String(gasLimitLower - 1n)); + expect(backButton).toHaveAttribute("aria-disabled", "true"); + await fireInput(limitInput, gasLimitLower.toString()); + expect(backButton).toHaveAttribute("aria-disabled", "false"); + await fireInput(limitInput, String(gasLimitUpper + 1n)); expect(backButton).toHaveAttribute("aria-disabled", "true"); - await fireInput(limitInput, 20000000); + await fireInput(limitInput, gasLimitUpper.toString()); expect(backButton).toHaveAttribute("aria-disabled", "false"); }); @@ -146,9 +157,9 @@ describe("Settings", () => { loginInfoStorageSpy.mockRestore(); }); - it("should clear local data, settings, and login info before logging out the user if the reset button is clicked and the user confirms the operation", async () => { + it("should clear local data, settings, and login info before logging out the user if the reset wallet button is clicked and the user confirms the operation", async () => { const { getByRole } = render(Settings); - const resetButton = getByRole("button", { name: /reset/i }); + const resetButton = getByRole("button", { name: /reset wallet/i }); await fireEvent.click(resetButton); @@ -167,7 +178,7 @@ describe("Settings", () => { confirmSpy.mockReturnValueOnce(false); const { getByRole } = render(Settings); - const resetButton = getByRole("button", { name: /reset/i }); + const resetButton = getByRole("button", { name: /reset wallet/i }); await fireEvent.click(resetButton); @@ -185,7 +196,7 @@ describe("Settings", () => { clearDataSpy.mockRejectedValueOnce(new Error("Clear data error")); const { container, getByRole } = render(Settings); - const resetButton = getByRole("button", { name: /reset/i }); + const resetButton = getByRole("button", { name: /reset wallet/i }); await fireEvent.click(resetButton); diff --git a/web-wallet/vite.config.js b/web-wallet/vite.config.js index 6f4b8babec..a008c54190 100644 --- a/web-wallet/vite.config.js +++ b/web-wallet/vite.config.js @@ -93,7 +93,7 @@ export default defineConfig(({ mode }) => { VITE_FEATURE_STAKE: "true", VITE_FEATURE_TRANSACTION_HISTORY: "true", VITE_FEATURE_TRANSFER: "true", - VITE_GAS_LIMIT_DEFAULT: "20000000", + VITE_GAS_LIMIT_DEFAULT: "100000000", VITE_GAS_LIMIT_LOWER: "10000000", VITE_GAS_LIMIT_UPPER: "1000000000", VITE_GAS_PRICE_DEFAULT: "1",